Skip to content

Commit

Permalink
Additional reestablish test (#1875)
Browse files Browse the repository at this point in the history
This test was added to lightning-kmp where this case wasn't correctly
handled: ACINQ/lightning-kmp#278

It is correctly handled by eclair, but an additional test doesn't hurt.
  • Loading branch information
t-bast committed Jul 16, 2021
1 parent ca51a2d commit 3ae9a4a
Showing 1 changed file with 53 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,53 @@ class OfflineStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
awaitCond(bob.stateName == NORMAL)
}

test("resume htlc settlement") { f =>
import f._

// Successfully send a first payment.
val (r1, htlc1) = addHtlc(15_000_000 msat, bob, alice, bob2alice, alice2bob)
crossSign(bob, alice, bob2alice, alice2bob)
fulfillHtlc(htlc1.id, r1, alice, bob, alice2bob, bob2alice)
crossSign(alice, bob, alice2bob, bob2alice)

// Send a second payment and disconnect right after the fulfill was signed.
val (r2, htlc2) = addHtlc(25_000_000 msat, bob, alice, bob2alice, alice2bob)
crossSign(bob, alice, bob2alice, alice2bob)
fulfillHtlc(htlc2.id, r2, alice, bob, alice2bob, bob2alice)
val sender = TestProbe()
alice ! CMD_SIGN(Some(sender.ref))
sender.expectMsgType[RES_SUCCESS[CMD_SIGN]]
alice2bob.expectMsgType[CommitSig]
alice2bob.forward(bob)
val revB = bob2alice.expectMsgType[RevokeAndAck]
bob2alice.expectMsgType[CommitSig]
disconnect(alice, bob)

reconnect(alice, bob, alice2bob, bob2alice)
val reestablishA = alice2bob.expectMsgType[ChannelReestablish]
assert(reestablishA.nextLocalCommitmentNumber === 4)
assert(reestablishA.nextRemoteRevocationNumber === 3)
val reestablishB = bob2alice.expectMsgType[ChannelReestablish]
assert(reestablishB.nextLocalCommitmentNumber === 5)
assert(reestablishB.nextRemoteRevocationNumber === 3)

bob2alice.forward(alice, reestablishB)
// alice does not re-send messages bob already received
alice2bob.expectNoMessage(100 millis)

alice2bob.forward(bob, reestablishA)
// bob re-sends its revocation and signature, alice then completes the update
bob2alice.expectMsg(revB)
bob2alice.forward(alice)
bob2alice.expectMsgType[CommitSig]
bob2alice.forward(alice)
alice2bob.expectMsgType[RevokeAndAck]
alice2bob.forward(bob)

assert(alice.stateData.asInstanceOf[DATA_NORMAL].commitments.localCommit.index === 4)
assert(bob.stateData.asInstanceOf[DATA_NORMAL].commitments.localCommit.index === 4)
}

test("discover that we have a revoked commitment") { f =>
import f._

Expand Down Expand Up @@ -258,20 +305,21 @@ class OfflineStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
reconnect(alice, bob, alice2bob, bob2alice)

// peers exchange channel_reestablish messages
alice2bob.expectMsgType[ChannelReestablish]
bob2alice.expectMsgType[ChannelReestablish]
val reestablishA = alice2bob.expectMsgType[ChannelReestablish]
val reestablishB = bob2alice.expectMsgType[ChannelReestablish]

// alice then realizes it has an old state...
bob2alice.forward(alice)
bob2alice.forward(alice, reestablishB)
// ... and ask bob to publish its current commitment
val error = alice2bob.expectMsgType[Error]
assert(error === Error(channelId(alice), PleasePublishYourCommitment(channelId(alice)).getMessage))

// alice now waits for bob to publish its commitment
awaitCond(alice.stateName == WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT)

// bob is nice and publishes its commitment
val bobCommitTx = bob.stateData.asInstanceOf[DATA_NORMAL].commitments.localCommit.commitTxAndRemoteSig.commitTx.tx
// bob publishes its commitment when it detects that alice has an outdated commitment
alice2bob.forward(bob, reestablishA)
val bobCommitTx = bob2blockchain.expectMsgType[PublishRawTx].tx
alice ! WatchFundingSpentTriggered(bobCommitTx)

// alice is able to claim its main output
Expand Down

0 comments on commit 3ae9a4a

Please sign in to comment.