lnwallet: add anchor size back to balance on coop close
To be spec compliant, we require the initiator to not pay the anchor values into fees on coop close. We extract the balance calculation into commitment.go, and add back the value of the anchors to the initiator's balance.
This commit is contained in:
parent
07a57ae778
commit
09a126b29f
@ -683,14 +683,37 @@ func testCommitHTLCSigTieBreak(t *testing.T, restart bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestCooperativeChannelClosure checks that the coop close process finishes
|
||||||
|
// with an agreement from both parties, and that the final balances of the
|
||||||
|
// close tx check out.
|
||||||
func TestCooperativeChannelClosure(t *testing.T) {
|
func TestCooperativeChannelClosure(t *testing.T) {
|
||||||
|
t.Run("tweakless", func(t *testing.T) {
|
||||||
|
testCoopClose(t, &coopCloseTestCase{
|
||||||
|
chanType: channeldb.SingleFunderTweaklessBit,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
t.Run("anchors", func(t *testing.T) {
|
||||||
|
testCoopClose(t, &coopCloseTestCase{
|
||||||
|
chanType: channeldb.SingleFunderTweaklessBit |
|
||||||
|
channeldb.AnchorOutputsBit,
|
||||||
|
anchorAmt: anchorSize * 2,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type coopCloseTestCase struct {
|
||||||
|
chanType channeldb.ChannelType
|
||||||
|
anchorAmt btcutil.Amount
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCoopClose(t *testing.T, testCase *coopCloseTestCase) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create a test channel which will be used for the duration of this
|
// Create a test channel which will be used for the duration of this
|
||||||
// unittest. The channel will be funded evenly with Alice having 5 BTC,
|
// unittest. The channel will be funded evenly with Alice having 5 BTC,
|
||||||
// and Bob having 5 BTC.
|
// and Bob having 5 BTC.
|
||||||
aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(
|
aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(
|
||||||
channeldb.SingleFunderTweaklessBit,
|
testCase.chanType,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create test channels: %v", err)
|
t.Fatalf("unable to create test channels: %v", err)
|
||||||
@ -707,7 +730,7 @@ func TestCooperativeChannelClosure(t *testing.T) {
|
|||||||
bobChannel.channelState.LocalCommitment.FeePerKw,
|
bobChannel.channelState.LocalCommitment.FeePerKw,
|
||||||
)
|
)
|
||||||
|
|
||||||
// We'll store with both Alice and Bob creating a new close proposal
|
// We'll start with both Alice and Bob creating a new close proposal
|
||||||
// with the same fee.
|
// with the same fee.
|
||||||
aliceFee := aliceChannel.CalcFee(aliceFeeRate)
|
aliceFee := aliceChannel.CalcFee(aliceFeeRate)
|
||||||
aliceSig, _, _, err := aliceChannel.CreateCloseProposal(
|
aliceSig, _, _, err := aliceChannel.CreateCloseProposal(
|
||||||
@ -728,7 +751,7 @@ func TestCooperativeChannelClosure(t *testing.T) {
|
|||||||
// With the proposals created, both sides should be able to properly
|
// With the proposals created, both sides should be able to properly
|
||||||
// process the other party's signature. This indicates that the
|
// process the other party's signature. This indicates that the
|
||||||
// transaction is well formed, and the signatures verify.
|
// transaction is well formed, and the signatures verify.
|
||||||
aliceCloseTx, _, err := bobChannel.CompleteCooperativeClose(
|
aliceCloseTx, bobTxBalance, err := bobChannel.CompleteCooperativeClose(
|
||||||
bobSig, aliceSig, bobDeliveryScript, aliceDeliveryScript,
|
bobSig, aliceSig, bobDeliveryScript, aliceDeliveryScript,
|
||||||
bobFee,
|
bobFee,
|
||||||
)
|
)
|
||||||
@ -737,7 +760,7 @@ func TestCooperativeChannelClosure(t *testing.T) {
|
|||||||
}
|
}
|
||||||
bobCloseSha := aliceCloseTx.TxHash()
|
bobCloseSha := aliceCloseTx.TxHash()
|
||||||
|
|
||||||
bobCloseTx, _, err := aliceChannel.CompleteCooperativeClose(
|
bobCloseTx, aliceTxBalance, err := aliceChannel.CompleteCooperativeClose(
|
||||||
aliceSig, bobSig, aliceDeliveryScript, bobDeliveryScript,
|
aliceSig, bobSig, aliceDeliveryScript, bobDeliveryScript,
|
||||||
aliceFee,
|
aliceFee,
|
||||||
)
|
)
|
||||||
@ -749,6 +772,32 @@ func TestCooperativeChannelClosure(t *testing.T) {
|
|||||||
if bobCloseSha != aliceCloseSha {
|
if bobCloseSha != aliceCloseSha {
|
||||||
t.Fatalf("alice and bob close transactions don't match: %v", err)
|
t.Fatalf("alice and bob close transactions don't match: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finally, make sure the final balances are correct from both's
|
||||||
|
// perspective.
|
||||||
|
aliceBalance := aliceChannel.channelState.LocalCommitment.
|
||||||
|
LocalBalance.ToSatoshis()
|
||||||
|
|
||||||
|
// The commit balance have had the initiator's (Alice) commitfee and
|
||||||
|
// any anchors subtracted, so add that back to the final expected
|
||||||
|
// balance. Alice also pays the coop close fee, so that must be
|
||||||
|
// subtracted.
|
||||||
|
commitFee := aliceChannel.channelState.LocalCommitment.CommitFee
|
||||||
|
expBalanceAlice := aliceBalance + commitFee +
|
||||||
|
testCase.anchorAmt - bobFee
|
||||||
|
if aliceTxBalance != expBalanceAlice {
|
||||||
|
t.Fatalf("expected balance %v got %v", expBalanceAlice,
|
||||||
|
aliceTxBalance)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bob is not the initiator, so his final balance should simply be
|
||||||
|
// equal to the latest commitment balance.
|
||||||
|
expBalanceBob := bobChannel.channelState.LocalCommitment.
|
||||||
|
LocalBalance.ToSatoshis()
|
||||||
|
if bobTxBalance != expBalanceBob {
|
||||||
|
t.Fatalf("expected bob's balance to be %v got %v",
|
||||||
|
expBalanceBob, bobTxBalance)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestForceClose checks that the resulting ForceCloseSummary is correct when a
|
// TestForceClose checks that the resulting ForceCloseSummary is correct when a
|
||||||
|
@ -675,11 +675,22 @@ func CoopCloseBalance(chanType channeldb.ChannelType, isInitiator bool,
|
|||||||
|
|
||||||
// We'll make sure we account for the complete balance by adding the
|
// We'll make sure we account for the complete balance by adding the
|
||||||
// current dangling commitment fee to the balance of the initiator.
|
// current dangling commitment fee to the balance of the initiator.
|
||||||
commitFee := localCommit.CommitFee
|
initiatorDelta := localCommit.CommitFee
|
||||||
|
|
||||||
|
// Since the initiator's balance also is stored after subtracting the
|
||||||
|
// anchor values, add that back in case this was an anchor commitment.
|
||||||
|
if chanType.HasAnchors() {
|
||||||
|
initiatorDelta += 2 * anchorSize
|
||||||
|
}
|
||||||
|
|
||||||
|
// The initiator will pay the full coop close fee, subtract that value
|
||||||
|
// from their balance.
|
||||||
|
initiatorDelta -= coopCloseFee
|
||||||
|
|
||||||
if isInitiator {
|
if isInitiator {
|
||||||
ourBalance = ourBalance - coopCloseFee + commitFee
|
ourBalance += initiatorDelta
|
||||||
} else {
|
} else {
|
||||||
theirBalance = theirBalance - coopCloseFee + commitFee
|
theirBalance += initiatorDelta
|
||||||
}
|
}
|
||||||
|
|
||||||
return ourBalance, theirBalance
|
return ourBalance, theirBalance
|
||||||
|
Loading…
Reference in New Issue
Block a user