@@ -770,29 +770,66 @@ func TestCommitHTLCSigCustomRecordSize(t *testing.T) {
770
770
}
771
771
772
772
// TestCooperativeChannelClosure checks that the coop close process finishes
773
- // with an agreement from both parties, and that the final balances of the
774
- // close tx check out.
773
+ // with an agreement from both parties, and that the final balances of the close
774
+ // tx check out.
775
775
func TestCooperativeChannelClosure (t * testing.T ) {
776
- t .Run ("tweakless" , func (t * testing.T ) {
777
- testCoopClose (t , & coopCloseTestCase {
778
- chanType : channeldb .SingleFunderTweaklessBit ,
779
- })
780
- })
781
- t .Run ("anchors" , func (t * testing.T ) {
782
- testCoopClose (t , & coopCloseTestCase {
783
- chanType : channeldb .SingleFunderTweaklessBit |
784
- channeldb .AnchorOutputsBit ,
785
- anchorAmt : AnchorSize * 2 ,
776
+ testCases := []struct {
777
+ name string
778
+ closeCase coopCloseTestCase
779
+ }{
780
+ {
781
+ name : "tweakless" ,
782
+ closeCase : coopCloseTestCase {
783
+ chanType : channeldb .SingleFunderTweaklessBit ,
784
+ },
785
+ },
786
+ {
787
+ name : "anchors" ,
788
+ closeCase : coopCloseTestCase {
789
+ chanType : channeldb .SingleFunderTweaklessBit |
790
+ channeldb .AnchorOutputsBit ,
791
+ anchorAmt : AnchorSize * 2 ,
792
+ },
793
+ },
794
+ {
795
+ name : "anchors local pay" ,
796
+ closeCase : coopCloseTestCase {
797
+ chanType : channeldb .SingleFunderTweaklessBit |
798
+ channeldb .AnchorOutputsBit ,
799
+ anchorAmt : AnchorSize * 2 ,
800
+ customPayer : fn .Some (lntypes .Local ),
801
+ },
802
+ },
803
+ {
804
+ name : "anchors remote pay" ,
805
+ closeCase : coopCloseTestCase {
806
+ chanType : channeldb .SingleFunderTweaklessBit |
807
+ channeldb .AnchorOutputsBit ,
808
+ anchorAmt : AnchorSize * 2 ,
809
+ customPayer : fn .Some (lntypes .Remote ),
810
+ },
811
+ },
812
+ }
813
+ for _ , testCase := range testCases {
814
+ t .Run (testCase .name , func (t * testing.T ) {
815
+ testCoopClose (t , testCase .closeCase )
786
816
})
787
- })
817
+ }
788
818
}
789
819
790
820
type coopCloseTestCase struct {
791
821
chanType channeldb.ChannelType
792
822
anchorAmt btcutil.Amount
823
+
824
+ customPayer fn.Option [lntypes.ChannelParty ]
825
+ }
826
+
827
+ type closeOpts struct {
828
+ aliceOpts []ChanCloseOpt
829
+ bobOpts []ChanCloseOpt
793
830
}
794
831
795
- func testCoopClose (t * testing.T , testCase * coopCloseTestCase ) {
832
+ func testCoopClose (t * testing.T , testCase coopCloseTestCase ) {
796
833
t .Parallel ()
797
834
798
835
// Create a test channel which will be used for the duration of this
@@ -813,17 +850,38 @@ func testCoopClose(t *testing.T, testCase *coopCloseTestCase) {
813
850
bobChannel .channelState .LocalCommitment .FeePerKw ,
814
851
)
815
852
853
+ customPayer := testCase .customPayer
854
+
855
+ closeOpts := fn .MapOptionZ (
856
+ customPayer , func (payer lntypes.ChannelParty ) closeOpts {
857
+ // If the local party is paying then from Alice's PoV,
858
+ // then local party is paying. From Bob's PoV, the
859
+ // remote party is paying. If the remote party is, then
860
+ // the opposite is true.
861
+ return closeOpts {
862
+ aliceOpts : []ChanCloseOpt {
863
+ WithCustomPayer (payer ),
864
+ },
865
+ bobOpts : []ChanCloseOpt {
866
+ WithCustomPayer (payer .CounterParty ()),
867
+ },
868
+ }
869
+ },
870
+ )
871
+
816
872
// We'll start with both Alice and Bob creating a new close proposal
817
873
// with the same fee.
818
874
aliceFee := aliceChannel .CalcFee (aliceFeeRate )
819
875
aliceSig , _ , _ , err := aliceChannel .CreateCloseProposal (
820
876
aliceFee , aliceDeliveryScript , bobDeliveryScript ,
877
+ closeOpts .aliceOpts ... ,
821
878
)
822
879
require .NoError (t , err , "unable to create alice coop close proposal" )
823
880
824
881
bobFee := bobChannel .CalcFee (bobFeeRate )
825
882
bobSig , _ , _ , err := bobChannel .CreateCloseProposal (
826
883
bobFee , bobDeliveryScript , aliceDeliveryScript ,
884
+ closeOpts .bobOpts ... ,
827
885
)
828
886
require .NoError (t , err , "unable to create bob coop close proposal" )
829
887
@@ -832,14 +890,14 @@ func testCoopClose(t *testing.T, testCase *coopCloseTestCase) {
832
890
// transaction is well formed, and the signatures verify.
833
891
aliceCloseTx , bobTxBalance , err := bobChannel .CompleteCooperativeClose (
834
892
bobSig , aliceSig , bobDeliveryScript , aliceDeliveryScript ,
835
- bobFee ,
893
+ bobFee , closeOpts . bobOpts ... ,
836
894
)
837
895
require .NoError (t , err , "unable to complete alice cooperative close" )
838
896
bobCloseSha := aliceCloseTx .TxHash ()
839
897
840
898
bobCloseTx , aliceTxBalance , err := aliceChannel .CompleteCooperativeClose (
841
899
aliceSig , bobSig , aliceDeliveryScript , bobDeliveryScript ,
842
- aliceFee ,
900
+ aliceFee , closeOpts . aliceOpts ... ,
843
901
)
844
902
require .NoError (t , err , "unable to complete bob cooperative close" )
845
903
aliceCloseSha := bobCloseTx .TxHash ()
@@ -848,18 +906,43 @@ func testCoopClose(t *testing.T, testCase *coopCloseTestCase) {
848
906
t .Fatalf ("alice and bob close transactions don't match: %v" , err )
849
907
}
850
908
851
- // Finally, make sure the final balances are correct from both's
852
- // perspective.
909
+ type chanFees struct {
910
+ alice btcutil.Amount
911
+ bob btcutil.Amount
912
+ }
913
+
914
+ // Compute the closing fees for each party. If not specified, Alice will
915
+ // always pay the fees. Otherwise, it depends on who the payer is.
916
+ closeFees := fn .MapOption (func (payer lntypes.ChannelParty ) chanFees {
917
+ var alice , bob btcutil.Amount
918
+
919
+ switch payer {
920
+ case lntypes .Local :
921
+ alice = bobFee
922
+ bob = 0
923
+ case lntypes .Remote :
924
+ bob = bobFee
925
+ alice = 0
926
+ }
927
+
928
+ return chanFees {
929
+ alice : alice ,
930
+ bob : bob ,
931
+ }
932
+ })(testCase .customPayer ).UnwrapOr (chanFees {alice : bobFee })
933
+
934
+ // Finally, make sure the final balances are correct from both
935
+ // perspectives.
853
936
aliceBalance := aliceChannel .channelState .LocalCommitment .
854
937
LocalBalance .ToSatoshis ()
855
938
856
- // The commit balance have had the initiator's (Alice) commitfee and
939
+ // The commit balance have had the initiator's (Alice) commit fee and
857
940
// any anchors subtracted, so add that back to the final expected
858
941
// balance. Alice also pays the coop close fee, so that must be
859
942
// subtracted.
860
943
commitFee := aliceChannel .channelState .LocalCommitment .CommitFee
861
944
expBalanceAlice := aliceBalance + commitFee +
862
- testCase .anchorAmt - bobFee
945
+ testCase .anchorAmt - closeFees . alice
863
946
if aliceTxBalance != expBalanceAlice {
864
947
t .Fatalf ("expected balance %v got %v" , expBalanceAlice ,
865
948
aliceTxBalance )
@@ -868,7 +951,7 @@ func testCoopClose(t *testing.T, testCase *coopCloseTestCase) {
868
951
// Bob is not the initiator, so his final balance should simply be
869
952
// equal to the latest commitment balance.
870
953
expBalanceBob := bobChannel .channelState .LocalCommitment .
871
- LocalBalance .ToSatoshis ()
954
+ LocalBalance .ToSatoshis () - closeFees . bob
872
955
if bobTxBalance != expBalanceBob {
873
956
t .Fatalf ("expected bob's balance to be %v got %v" ,
874
957
expBalanceBob , bobTxBalance )
0 commit comments