diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 4c5bace6..ab841031 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -2428,23 +2428,27 @@ func (lc *LightningChannel) createCommitmentTx(c *commitment, } var ( - delay uint32 - delayBalance, p2wkhBalance btcutil.Amount + commitTx *wire.MsgTx + err error ) - if c.isOurs { - delay = uint32(lc.channelState.LocalChanCfg.CsvDelay) - delayBalance = ourBalance.ToSatoshis() - p2wkhBalance = theirBalance.ToSatoshis() - } else { - delay = uint32(lc.channelState.RemoteChanCfg.CsvDelay) - delayBalance = theirBalance.ToSatoshis() - p2wkhBalance = ourBalance.ToSatoshis() - } - // Generate a new commitment transaction with all the latest - // unsettled/un-timed out HTLCs. - commitTx, err := CreateCommitTx(lc.fundingTxIn(), keyRing, delay, - delayBalance, p2wkhBalance, c.dustLimit) + // Depending on whether the transaction is ours or not, we call + // CreateCommitTx with parameters mathcing the perspective, to generate + // a new commitment transaction with all the latest unsettled/un-timed + // out HTLCs. + if c.isOurs { + commitTx, err = CreateCommitTx( + lc.fundingTxIn(), keyRing, &lc.channelState.LocalChanCfg, + &lc.channelState.RemoteChanCfg, ourBalance.ToSatoshis(), + theirBalance.ToSatoshis(), + ) + } else { + commitTx, err = CreateCommitTx( + lc.fundingTxIn(), keyRing, &lc.channelState.RemoteChanCfg, + &lc.channelState.LocalChanCfg, theirBalance.ToSatoshis(), + ourBalance.ToSatoshis(), + ) + } if err != nil { return err } @@ -6216,32 +6220,39 @@ func (lc *LightningChannel) generateRevocation(height uint64) (*lnwire.RevokeAnd } // CreateCommitTx creates a commitment transaction, spending from specified -// funding output. The commitment transaction contains two outputs: one paying -// to the "owner" of the commitment transaction which can be spent after a -// relative block delay or revocation event, and the other paying the -// counterparty within the channel, which can be spent immediately. -func CreateCommitTx(fundingOutput wire.TxIn, - keyRing *CommitmentKeyRing, csvTimeout uint32, - amountToSelf, amountToThem, dustLimit btcutil.Amount) (*wire.MsgTx, error) { +// funding output. The commitment transaction contains two outputs: one local +// output paying to the "owner" of the commitment transaction which can be +// spent after a relative block delay or revocation event, and a remote output +// paying the counterparty within the channel, which can be spent immediately +// or after a delay depending on the commitment type.. +func CreateCommitTx(fundingOutput wire.TxIn, keyRing *CommitmentKeyRing, + localChanCfg, remoteChanCfg *channeldb.ChannelConfig, + amountToLocal, amountToRemote btcutil.Amount) (*wire.MsgTx, error) { // First, we create the script for the delayed "pay-to-self" output. // This output has 2 main redemption clauses: either we can redeem the // output after a relative block delay, or the remote node can claim // the funds with the revocation key if we broadcast a revoked // commitment transaction. - ourRedeemScript, err := input.CommitScriptToSelf(csvTimeout, keyRing.DelayKey, - keyRing.RevocationKey) + toLocalRedeemScript, err := input.CommitScriptToSelf( + uint32(localChanCfg.CsvDelay), keyRing.DelayKey, + keyRing.RevocationKey, + ) if err != nil { return nil, err } - payToUsScriptHash, err := input.WitnessScriptHash(ourRedeemScript) + toLocalScriptHash, err := input.WitnessScriptHash( + toLocalRedeemScript, + ) if err != nil { return nil, err } - // Next, we create the script paying to them. This is just a regular - // P2WPKH output, without any added CSV delay. - theirWitnessKeyHash, err := input.CommitScriptUnencumbered(keyRing.NoDelayKey) + // Next, we create the script paying to the remote. This is just a + // regular P2WPKH output, without any added CSV delay. + toRemoteWitnessKeyHash, err := input.CommitScriptUnencumbered( + keyRing.NoDelayKey, + ) if err != nil { return nil, err } @@ -6253,16 +6264,16 @@ func CreateCommitTx(fundingOutput wire.TxIn, commitTx.AddTxIn(&fundingOutput) // Avoid creating dust outputs within the commitment transaction. - if amountToSelf >= dustLimit { + if amountToLocal >= localChanCfg.DustLimit { commitTx.AddTxOut(&wire.TxOut{ - PkScript: payToUsScriptHash, - Value: int64(amountToSelf), + PkScript: toLocalScriptHash, + Value: int64(amountToLocal), }) } - if amountToThem >= dustLimit { + if amountToRemote >= localChanCfg.DustLimit { commitTx.AddTxOut(&wire.TxOut{ - PkScript: theirWitnessKeyHash, - Value: int64(amountToThem), + PkScript: toRemoteWitnessKeyHash, + Value: int64(amountToRemote), }) } diff --git a/lnwallet/transactions_test.go b/lnwallet/transactions_test.go index 47022e86..24c2f455 100644 --- a/lnwallet/transactions_test.go +++ b/lnwallet/transactions_test.go @@ -1015,7 +1015,7 @@ func testSpendValidation(t *testing.T, tweakless bool) { fakeFundingTxIn := wire.NewTxIn(fundingOut, nil, nil) const channelBalance = btcutil.Amount(1 * 10e8) - const csvTimeout = uint32(5) + const csvTimeout = 5 // We also set up set some resources for the commitment transaction. // Each side currently has 1 BTC within the channel, with a total @@ -1050,6 +1050,20 @@ func testSpendValidation(t *testing.T, tweakless bool) { Privkeys: []*btcec.PrivateKey{aliceKeyPriv}, } + aliceChanCfg := &channeldb.ChannelConfig{ + ChannelConstraints: channeldb.ChannelConstraints{ + DustLimit: DefaultDustLimit(), + CsvDelay: csvTimeout, + }, + } + + bobChanCfg := &channeldb.ChannelConfig{ + ChannelConstraints: channeldb.ChannelConstraints{ + DustLimit: DefaultDustLimit(), + CsvDelay: csvTimeout, + }, + } + // With all the test data set up, we create the commitment transaction. // We only focus on a single party's transactions, as the scripts are // identical with the roles reversed. @@ -1063,8 +1077,8 @@ func testSpendValidation(t *testing.T, tweakless bool) { NoDelayKey: bobPayKey, } commitmentTx, err := CreateCommitTx( - *fakeFundingTxIn, keyRing, csvTimeout, channelBalance, - channelBalance, DefaultDustLimit(), + *fakeFundingTxIn, keyRing, aliceChanCfg, bobChanCfg, + channelBalance, channelBalance, ) if err != nil { t.Fatalf("unable to create commitment transaction: %v", nil) diff --git a/lnwallet/wallet.go b/lnwallet/wallet.go index a6b9b875..61b7cfee 100644 --- a/lnwallet/wallet.go +++ b/lnwallet/wallet.go @@ -784,9 +784,10 @@ func CreateCommitmentTxns(localBalance, remoteBalance btcutil.Amount, theirChanCfg, ) - ourCommitTx, err := CreateCommitTx(fundingTxIn, localCommitmentKeys, - uint32(ourChanCfg.CsvDelay), localBalance, remoteBalance, - ourChanCfg.DustLimit) + ourCommitTx, err := CreateCommitTx( + fundingTxIn, localCommitmentKeys, ourChanCfg, theirChanCfg, + localBalance, remoteBalance, + ) if err != nil { return nil, nil, err } @@ -796,9 +797,10 @@ func CreateCommitmentTxns(localBalance, remoteBalance btcutil.Amount, return nil, nil, err } - theirCommitTx, err := CreateCommitTx(fundingTxIn, remoteCommitmentKeys, - uint32(theirChanCfg.CsvDelay), remoteBalance, localBalance, - theirChanCfg.DustLimit) + theirCommitTx, err := CreateCommitTx( + fundingTxIn, remoteCommitmentKeys, theirChanCfg, ourChanCfg, + remoteBalance, localBalance, + ) if err != nil { return nil, nil, err }