@@ -876,7 +876,7 @@ class WaitForDualFundingConfirmedStateSpec extends TestKitBaseClass with Fixture
876
876
assert(alice.stateName == WAIT_FOR_DUAL_FUNDING_CONFIRMED )
877
877
}
878
878
879
- test( " recv INPUT_DISCONNECTED (unsigned rbf attempt) " , Tag ( ChannelStateTestsTags . DualFunding )) { f =>
879
+ private def initiateRbf ( f : FixtureParam ) : Unit = {
880
880
import f ._
881
881
882
882
alice ! CMD_BUMP_FUNDING_FEE (TestProbe ().ref, TestConstants .feeratePerKw * 1.1 , fundingFeeBudget = 100_000 .sat, 0 , None )
@@ -900,28 +900,43 @@ class WaitForDualFundingConfirmedStateSpec extends TestKitBaseClass with Fixture
900
900
alice2bob.forward(bob)
901
901
bob2alice.expectMsgType[TxComplete ]
902
902
bob2alice.forward(alice)
903
- alice2bob.expectMsgType[TxComplete ] // bob doesn't receive alice's tx_complete
904
- alice2bob.expectMsgType[CommitSig ] // bob doesn't receive alice's commit_sig
903
+ }
905
904
906
- awaitCond(alice.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status.isInstanceOf [DualFundingStatus .RbfWaitingForSigs ])
907
- val rbfTx = alice.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status.asInstanceOf [DualFundingStatus .RbfWaitingForSigs ].signingSession.fundingTx
908
- assert(bob.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status.isInstanceOf [DualFundingStatus .RbfInProgress ])
905
+ private def reconnectRbf (f : FixtureParam ): (ChannelReestablish , ChannelReestablish ) = {
906
+ import f ._
909
907
910
908
alice ! INPUT_DISCONNECTED
911
909
awaitCond(alice.stateName == OFFLINE )
912
- assert(alice.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status.isInstanceOf [DualFundingStatus .RbfWaitingForSigs ])
913
910
bob ! INPUT_DISCONNECTED
914
911
awaitCond(bob.stateName == OFFLINE )
915
- assert(bob.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status == DualFundingStatus .WaitingForConfirmations )
916
912
917
913
val aliceInit = Init (alice.underlyingActor.nodeParams.features.initFeatures())
918
914
val bobInit = Init (bob.underlyingActor.nodeParams.features.initFeatures())
919
915
alice ! INPUT_RECONNECTED (bob, aliceInit, bobInit)
920
916
bob ! INPUT_RECONNECTED (alice, bobInit, aliceInit)
921
- assert( alice2bob.expectMsgType[ChannelReestablish ].nextFundingTxId_opt.contains(rbfTx.txId))
917
+ val channelReestablishAlice = alice2bob.expectMsgType[ChannelReestablish ]
922
918
alice2bob.forward(bob)
923
- assert( bob2alice.expectMsgType[ChannelReestablish ].nextFundingTxId_opt.isEmpty)
919
+ val channelReestablishBob = bob2alice.expectMsgType[ChannelReestablish ]
924
920
bob2alice.forward(alice)
921
+ (channelReestablishAlice, channelReestablishBob)
922
+ }
923
+
924
+ test(" recv INPUT_DISCONNECTED (unsigned rbf attempt)" , Tag (ChannelStateTestsTags .DualFunding )) { f =>
925
+ import f ._
926
+
927
+ initiateRbf(f)
928
+ alice2bob.expectMsgType[TxComplete ] // bob doesn't receive alice's tx_complete
929
+ alice2bob.expectMsgType[CommitSig ] // bob doesn't receive alice's commit_sig
930
+
931
+ awaitCond(alice.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status.isInstanceOf [DualFundingStatus .RbfWaitingForSigs ])
932
+ val rbfTxId = alice.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status.asInstanceOf [DualFundingStatus .RbfWaitingForSigs ].signingSession.fundingTx.txId
933
+ assert(bob.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status.isInstanceOf [DualFundingStatus .RbfInProgress ])
934
+
935
+ val (channelReestablishAlice, channelReestablishBob) = reconnectRbf(f)
936
+ assert(channelReestablishAlice.nextFundingTxId_opt.contains(rbfTxId))
937
+ assert(channelReestablishAlice.nextLocalCommitmentNumber == 1 )
938
+ assert(channelReestablishBob.nextFundingTxId_opt.isEmpty)
939
+ assert(channelReestablishBob.nextLocalCommitmentNumber == 1 )
925
940
926
941
// Bob detects that Alice stored an old RBF attempt and tells her to abort.
927
942
bob2alice.expectMsgType[TxAbort ]
@@ -934,71 +949,117 @@ class WaitForDualFundingConfirmedStateSpec extends TestKitBaseClass with Fixture
934
949
bob2alice.expectNoMessage(100 millis)
935
950
}
936
951
937
- test(" recv INPUT_DISCONNECTED (signed rbf attempt )" , Tag (ChannelStateTestsTags .DualFunding )) { f =>
952
+ test(" recv INPUT_DISCONNECTED (rbf commit_sig partially received )" , Tag (ChannelStateTestsTags .DualFunding )) { f =>
938
953
import f ._
939
954
940
- val currentFundingTxId = alice.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].latestFundingTx.sharedTx.txId
941
- alice ! CMD_BUMP_FUNDING_FEE (TestProbe ().ref, TestConstants .feeratePerKw * 1.1 , fundingFeeBudget = 100_000 .sat, 0 , None )
942
- alice2bob.expectMsgType[TxInitRbf ]
955
+ initiateRbf(f)
956
+ alice2bob.expectMsgType[TxComplete ]
943
957
alice2bob.forward(bob)
944
- bob2alice.expectMsgType[TxAckRbf ]
945
- bob2alice.forward(alice)
946
- alice2bob.expectMsgType[TxAddInput ]
958
+ alice2bob.expectMsgType[CommitSig ]
947
959
alice2bob.forward(bob)
948
- bob2alice.expectMsgType[TxAddInput ]
949
- bob2alice.forward(alice)
950
- alice2bob.expectMsgType[TxAddInput ]
960
+ bob2alice.expectMsgType[CommitSig ] // Alice doesn't receive Bob's commit_sig
961
+ bob2alice.expectMsgType[TxSignatures ] // Alice doesn't receive Bob's tx_signatures
962
+ awaitCond(alice.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status.isInstanceOf [DualFundingStatus .RbfWaitingForSigs ])
963
+ awaitCond(bob.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status == DualFundingStatus .WaitingForConfirmations )
964
+ val rbfTxId = alice.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status.asInstanceOf [DualFundingStatus .RbfWaitingForSigs ].signingSession.fundingTx.txId
965
+
966
+ val (channelReestablishAlice, channelReestablishBob) = reconnectRbf(f)
967
+ assert(channelReestablishAlice.nextFundingTxId_opt.contains(rbfTxId))
968
+ assert(channelReestablishAlice.nextLocalCommitmentNumber == 1 )
969
+ assert(channelReestablishBob.nextFundingTxId_opt.contains(rbfTxId))
970
+ assert(channelReestablishBob.nextLocalCommitmentNumber == 1 )
971
+
972
+ // Alice and Bob exchange signatures and complete the RBF attempt.
973
+ alice2bob.expectMsgType[CommitSig ]
951
974
alice2bob.forward(bob)
952
- bob2alice.expectMsgType[TxAddInput ]
975
+ bob2alice.expectMsgType[CommitSig ]
953
976
bob2alice.forward(alice)
954
- alice2bob.expectMsgType[TxAddOutput ]
955
- alice2bob.forward(bob)
956
- bob2alice.expectMsgType[TxAddOutput ]
977
+ bob2alice.expectMsgType[TxSignatures ]
957
978
bob2alice.forward(alice)
958
- alice2bob.expectMsgType[TxAddOutput ]
979
+ alice2bob.expectMsgType[TxSignatures ]
959
980
alice2bob.forward(bob)
960
- bob2alice.expectMsgType[TxComplete ]
961
- bob2alice.forward(alice)
981
+ val nextFundingTx = alice.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].latestFundingTx.sharedTx.asInstanceOf [FullySignedSharedTransaction ]
982
+ assert(aliceListener.expectMsgType[TransactionPublished ].tx.txid == nextFundingTx.signedTx.txid)
983
+ assert(alice2blockchain.expectMsgType[WatchFundingConfirmed ].txId == nextFundingTx.signedTx.txid)
984
+ assert(bobListener.expectMsgType[TransactionPublished ].tx.txid == nextFundingTx.signedTx.txid)
985
+ assert(bob2blockchain.expectMsgType[WatchFundingConfirmed ].txId == nextFundingTx.signedTx.txid)
986
+ awaitCond(alice.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status == DualFundingStatus .WaitingForConfirmations )
987
+ awaitCond(bob.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status == DualFundingStatus .WaitingForConfirmations )
988
+ }
989
+
990
+ test(" recv INPUT_DISCONNECTED (rbf commit_sig received)" , Tag (ChannelStateTestsTags .DualFunding )) { f =>
991
+ import f ._
992
+
993
+ initiateRbf(f)
962
994
alice2bob.expectMsgType[TxComplete ]
963
995
alice2bob.forward(bob)
964
- bob2alice.expectMsgType[CommitSig ] // alice doesn't receive bob's commit_sig
965
- alice2bob.expectMsgType[CommitSig ] // bob doesn't receive alice's commit_sig
966
-
996
+ alice2bob.expectMsgType[CommitSig ]
997
+ alice2bob.forward(bob)
998
+ bob2alice.expectMsgType[CommitSig ]
999
+ bob2alice.forward(alice)
1000
+ bob2alice.expectMsgType[TxSignatures ] // Alice doesn't receive Bob's tx_signatures
967
1001
awaitCond(alice.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status.isInstanceOf [DualFundingStatus .RbfWaitingForSigs ])
968
- awaitCond(bob.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status. isInstanceOf [ DualFundingStatus .RbfWaitingForSigs ] )
1002
+ awaitCond(bob.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status == DualFundingStatus .WaitingForConfirmations )
969
1003
val rbfTx = alice.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status.asInstanceOf [DualFundingStatus .RbfWaitingForSigs ].signingSession.fundingTx
970
1004
971
- alice ! INPUT_DISCONNECTED
972
- awaitCond(alice.stateName == OFFLINE )
973
- assert(alice.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status.isInstanceOf [DualFundingStatus .RbfWaitingForSigs ])
974
- bob ! INPUT_DISCONNECTED
975
- awaitCond(bob.stateName == OFFLINE )
976
- assert(bob.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status.isInstanceOf [DualFundingStatus .RbfWaitingForSigs ])
1005
+ val (channelReestablishAlice, channelReestablishBob) = reconnectRbf(f)
1006
+ assert(channelReestablishAlice.nextFundingTxId_opt.contains(rbfTx.txId))
1007
+ assert(channelReestablishAlice.nextLocalCommitmentNumber == 1 )
1008
+ assert(channelReestablishBob.nextFundingTxId_opt.contains(rbfTx.txId))
1009
+ assert(channelReestablishBob.nextLocalCommitmentNumber == 1 )
977
1010
978
- val aliceInit = Init (alice.underlyingActor.nodeParams.features.initFeatures())
979
- val bobInit = Init (bob.underlyingActor.nodeParams.features.initFeatures())
980
- alice ! INPUT_RECONNECTED (bob, aliceInit, bobInit)
981
- bob ! INPUT_RECONNECTED (alice, bobInit, aliceInit)
982
- assert(alice2bob.expectMsgType[ChannelReestablish ].nextFundingTxId_opt.contains(rbfTx.txId))
1011
+ // Alice and Bob exchange signatures and complete the RBF attempt.
1012
+ alice2bob.expectMsgType[CommitSig ]
983
1013
alice2bob.forward(bob)
984
- assert(bob2alice.expectMsgType[ChannelReestablish ].nextFundingTxId_opt.contains(rbfTx.txId))
1014
+ bob2alice.expectMsgType[CommitSig ]
1015
+ bob2alice.forward(alice)
1016
+ bob2alice.expectMsgType[TxSignatures ]
985
1017
bob2alice.forward(alice)
1018
+ alice2bob.expectMsgType[TxSignatures ]
1019
+ alice2bob.forward(bob)
1020
+ val nextFundingTx = alice.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].latestFundingTx.sharedTx.asInstanceOf [FullySignedSharedTransaction ]
1021
+ assert(aliceListener.expectMsgType[TransactionPublished ].tx.txid == nextFundingTx.signedTx.txid)
1022
+ assert(alice2blockchain.expectMsgType[WatchFundingConfirmed ].txId == nextFundingTx.signedTx.txid)
1023
+ assert(bobListener.expectMsgType[TransactionPublished ].tx.txid == nextFundingTx.signedTx.txid)
1024
+ assert(bob2blockchain.expectMsgType[WatchFundingConfirmed ].txId == nextFundingTx.signedTx.txid)
1025
+ awaitCond(alice.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status == DualFundingStatus .WaitingForConfirmations )
1026
+ awaitCond(bob.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status == DualFundingStatus .WaitingForConfirmations )
1027
+ }
986
1028
987
- // Alice and Bob exchange signatures and complete the RBF attempt.
1029
+ test(" recv INPUT_DISCONNECTED (rbf tx_signatures partially received)" , Tag (ChannelStateTestsTags .DualFunding )) { f =>
1030
+ import f ._
1031
+
1032
+ val currentFundingTxId = alice.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].latestFundingTx.sharedTx.txId
1033
+ initiateRbf(f)
1034
+ alice2bob.expectMsgType[TxComplete ]
1035
+ alice2bob.forward(bob)
988
1036
alice2bob.expectMsgType[CommitSig ]
989
1037
alice2bob.forward(bob)
990
1038
bob2alice.expectMsgType[CommitSig ]
991
1039
bob2alice.forward(alice)
992
1040
bob2alice.expectMsgType[TxSignatures ]
993
1041
bob2alice.forward(alice)
1042
+ alice2bob.expectMsgType[TxSignatures ] // Bob doesn't receive Alice's tx_signatures
1043
+ awaitCond(alice.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status == DualFundingStatus .WaitingForConfirmations )
1044
+ awaitCond(bob.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status == DualFundingStatus .WaitingForConfirmations )
1045
+ val rbfTxId = alice.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].latestFundingTx.sharedTx.txId
1046
+ assert(rbfTxId != currentFundingTxId)
1047
+
1048
+ val (channelReestablishAlice, channelReestablishBob) = reconnectRbf(f)
1049
+ assert(channelReestablishAlice.nextFundingTxId_opt.isEmpty)
1050
+ assert(channelReestablishAlice.nextLocalCommitmentNumber == 1 )
1051
+ assert(channelReestablishBob.nextFundingTxId_opt.contains(rbfTxId))
1052
+ assert(channelReestablishBob.nextLocalCommitmentNumber == 1 )
1053
+
1054
+ // Alice and Bob exchange signatures and complete the RBF attempt.
1055
+ bob2alice.expectNoMessage(100 millis)
994
1056
alice2bob.expectMsgType[TxSignatures ]
995
1057
alice2bob.forward(bob)
996
1058
val nextFundingTx = alice.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].latestFundingTx.sharedTx.asInstanceOf [FullySignedSharedTransaction ]
997
1059
assert(aliceListener.expectMsgType[TransactionPublished ].tx.txid == nextFundingTx.signedTx.txid)
998
1060
assert(alice2blockchain.expectMsgType[WatchFundingConfirmed ].txId == nextFundingTx.signedTx.txid)
999
1061
assert(bobListener.expectMsgType[TransactionPublished ].tx.txid == nextFundingTx.signedTx.txid)
1000
1062
assert(bob2blockchain.expectMsgType[WatchFundingConfirmed ].txId == nextFundingTx.signedTx.txid)
1001
- assert(currentFundingTxId != nextFundingTx.txId)
1002
1063
awaitCond(alice.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status == DualFundingStatus .WaitingForConfirmations )
1003
1064
awaitCond(bob.stateData.asInstanceOf [DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED ].status == DualFundingStatus .WaitingForConfirmations )
1004
1065
}
0 commit comments