From b9516b7cddc85a59b61c39267516f6c0e60de37e Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 14 Jul 2017 21:04:29 +0200 Subject: [PATCH] lnwallet: make CreateCloseProposal take absolute fee instead of fee rate --- lnwallet/channel.go | 16 ++++++++++------ lnwallet/channel_test.go | 32 ++++++++++++++++++-------------- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 4dce1ffc..e6f6a089 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -3671,14 +3671,14 @@ func (lc *LightningChannel) ForceClose() (*ForceCloseSummary, error) { // // TODO(roasbeef): caller should initiate signal to reject all incoming HTLCs, // settle any in flight. -func (lc *LightningChannel) CreateCloseProposal(feeRate uint64, +func (lc *LightningChannel) CreateCloseProposal(proposedFee uint64, localDeliveryScript, remoteDeliveryScript []byte) ([]byte, uint64, error) { lc.Lock() defer lc.Unlock() - // If we're already closing the channel, then ignore this request. - if lc.status == channelClosing || lc.status == channelClosed { + // If we've already closed the channel, then ignore this request. + if lc.status == channelClosed { // TODO(roasbeef): check to ensure no pending payments return nil, 0, ErrChanClosing } @@ -3686,7 +3686,6 @@ func (lc *LightningChannel) CreateCloseProposal(feeRate uint64, // Subtract the proposed fee from the appropriate balance, taking care // not to persist the adjusted balance, as the feeRate may change // during the channel closing process. - proposedFee := (feeRate * uint64(commitWeight)) / 1000 ourBalance := lc.channelState.LocalBalance theirBalance := lc.channelState.RemoteBalance @@ -3734,7 +3733,7 @@ func (lc *LightningChannel) CreateCloseProposal(feeRate uint64, // signatures including the proper sighash byte. func (lc *LightningChannel) CompleteCooperativeClose(localSig, remoteSig, localDeliveryScript, remoteDeliveryScript []byte, - feeRate uint64) (*wire.MsgTx, error) { + proposedFee uint64) (*wire.MsgTx, error) { lc.Lock() defer lc.Unlock() @@ -3748,7 +3747,6 @@ func (lc *LightningChannel) CompleteCooperativeClose(localSig, remoteSig, // Subtract the proposed fee from the appropriate balance, taking care // not to persist the adjusted balance, as the feeRate may change // during the channel closing process. - proposedFee := (feeRate * uint64(commitWeight)) / 1000 ourBalance := lc.channelState.LocalBalance theirBalance := lc.channelState.RemoteBalance @@ -3947,3 +3945,9 @@ func CreateCooperativeCloseTx(fundingTxIn *wire.TxIn, return closeTx } + +// CalcFee returns the commitment fee to use for the given +// fee rate (fee-per-kw). +func (lc *LightningChannel) CalcFee(feeRate uint64) uint64 { + return (feeRate * uint64(commitWeight)) / 1000 +} diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index c43896b0..dc4cd912 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -737,17 +737,19 @@ func TestCooperativeChannelClosure(t *testing.T) { bobFeeRate := uint64(bobChannel.channelState.FeePerKw) // We'll store with both Alice and Bob creating a new close proposal - // with the same fee rate. + // with the same fee. + aliceFee := aliceChannel.CalcFee(aliceFeeRate) aliceSig, _, err := aliceChannel.CreateCloseProposal( - aliceFeeRate, aliceDeliveryScript, bobDeliveryScript, + aliceFee, aliceDeliveryScript, bobDeliveryScript, ) if err != nil { t.Fatalf("unable to create alice coop close proposal: %v", err) } aliceCloseSig := append(aliceSig, byte(txscript.SigHashAll)) + bobFee := bobChannel.CalcFee(bobFeeRate) bobSig, _, err := bobChannel.CreateCloseProposal( - bobFeeRate, bobDeliveryScript, aliceDeliveryScript, + bobFee, bobDeliveryScript, aliceDeliveryScript, ) if err != nil { t.Fatalf("unable to create bob coop close proposal: %v", err) @@ -759,7 +761,7 @@ func TestCooperativeChannelClosure(t *testing.T) { // transaction is well formed, and the signatures verify. aliceCloseTx, err := bobChannel.CompleteCooperativeClose( bobCloseSig, aliceCloseSig, bobDeliveryScript, - aliceDeliveryScript, bobFeeRate) + aliceDeliveryScript, bobFee) if err != nil { t.Fatalf("unable to complete alice cooperative close: %v", err) } @@ -767,7 +769,7 @@ func TestCooperativeChannelClosure(t *testing.T) { bobCloseTx, err := aliceChannel.CompleteCooperativeClose( aliceCloseSig, bobCloseSig, aliceDeliveryScript, - bobDeliveryScript, aliceFeeRate) + bobDeliveryScript, aliceFee) if err != nil { t.Fatalf("unable to complete bob cooperative close: %v", err) } @@ -1590,14 +1592,16 @@ func TestCooperativeCloseDustAdherence(t *testing.T) { // Both sides currently have over 1 BTC settled as part of their // balances. As a result, performing a cooperative closure now result // in both sides having an output within the closure transaction. - aliceSig, _, err := aliceChannel.CreateCloseProposal(aliceFeeRate, + aliceFee := aliceChannel.CalcFee(aliceFeeRate) + aliceSig, _, err := aliceChannel.CreateCloseProposal(aliceFee, aliceDeliveryScript, bobDeliveryScript) if err != nil { t.Fatalf("unable to close channel: %v", err) } aliceCloseSig := append(aliceSig, byte(txscript.SigHashAll)) - bobSig, _, err := bobChannel.CreateCloseProposal(bobFeeRate, + bobFee := bobChannel.CalcFee(bobFeeRate) + bobSig, _, err := bobChannel.CreateCloseProposal(bobFee, bobDeliveryScript, aliceDeliveryScript) if err != nil { t.Fatalf("unable to close channel: %v", err) @@ -1606,7 +1610,7 @@ func TestCooperativeCloseDustAdherence(t *testing.T) { closeTx, err := bobChannel.CompleteCooperativeClose( bobCloseSig, aliceCloseSig, - bobDeliveryScript, aliceDeliveryScript, bobFeeRate) + bobDeliveryScript, aliceDeliveryScript, bobFee) if err != nil { t.Fatalf("unable to accept channel close: %v", err) } @@ -1628,14 +1632,14 @@ func TestCooperativeCloseDustAdherence(t *testing.T) { // Attempt another cooperative channel closure. It should succeed // without any issues. - aliceSig, _, err = aliceChannel.CreateCloseProposal(aliceFeeRate, + aliceSig, _, err = aliceChannel.CreateCloseProposal(aliceFee, aliceDeliveryScript, bobDeliveryScript) if err != nil { t.Fatalf("unable to close channel: %v", err) } aliceCloseSig = append(aliceSig, byte(txscript.SigHashAll)) - bobSig, _, err = bobChannel.CreateCloseProposal(bobFeeRate, + bobSig, _, err = bobChannel.CreateCloseProposal(bobFee, bobDeliveryScript, aliceDeliveryScript) if err != nil { t.Fatalf("unable to close channel: %v", err) @@ -1644,7 +1648,7 @@ func TestCooperativeCloseDustAdherence(t *testing.T) { closeTx, err = bobChannel.CompleteCooperativeClose( bobCloseSig, aliceCloseSig, - bobDeliveryScript, aliceDeliveryScript, bobFeeRate) + bobDeliveryScript, aliceDeliveryScript, bobFee) if err != nil { t.Fatalf("unable to accept channel close: %v", err) } @@ -1667,14 +1671,14 @@ func TestCooperativeCloseDustAdherence(t *testing.T) { // Our final attempt at another cooperative channel closure. It should // succeed without any issues. - aliceSig, _, err = aliceChannel.CreateCloseProposal(aliceFeeRate, + aliceSig, _, err = aliceChannel.CreateCloseProposal(aliceFee, aliceDeliveryScript, bobDeliveryScript) if err != nil { t.Fatalf("unable to close channel: %v", err) } aliceCloseSig = append(aliceSig, byte(txscript.SigHashAll)) - bobSig, _, err = bobChannel.CreateCloseProposal(bobFeeRate, + bobSig, _, err = bobChannel.CreateCloseProposal(bobFee, bobDeliveryScript, aliceDeliveryScript) if err != nil { t.Fatalf("unable to close channel: %v", err) @@ -1683,7 +1687,7 @@ func TestCooperativeCloseDustAdherence(t *testing.T) { closeTx, err = bobChannel.CompleteCooperativeClose( bobCloseSig, aliceCloseSig, - bobDeliveryScript, aliceDeliveryScript, bobFeeRate) + bobDeliveryScript, aliceDeliveryScript, bobFee) if err != nil { t.Fatalf("unable to accept channel close: %v", err) }