From 07629e5da10fd0ac88bf5aa27ba6666cf8b59482 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Mon, 4 Jun 2018 14:29:37 +0200 Subject: [PATCH] lnwallet/channel: use FullySynced to check chanSync special case We check if the channel is FullySynced instead of comparing the local and remote commit chain heights, as the heights might not be in sync. Instead we call FullySynced which recently was modified to use compare the message indexes instead, which is _should_ really be in sync between the chains. The test TestChanSyncOweRevocationAndCommitForceTransition is altered to ensure the two chains at different heights before the test is started, to trigger the case that would previously fail to resend the commitment signature. --- lnwallet/channel.go | 3 +-- lnwallet/channel_test.go | 52 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index a3e4e537e..3eb5713ba 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -3182,8 +3182,7 @@ func (lc *LightningChannel) ProcessChanSyncMsg( // but died before the signature was sent. We re-transmit our // revocation, but also initiate a state transition to re-sync // them. - if lc.localCommitChain.tip().height > - lc.remoteCommitChain.tip().height { + if !lc.FullySynced() { commitSig, htlcSigs, err := lc.SignNextCommitment() switch { diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index d0beffa60..bfc23299c 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -3280,16 +3280,17 @@ func TestChanSyncOweRevocationAndCommitForceTransition(t *testing.T) { var bobPreimage [32]byte copy(bobPreimage[:], bytes.Repeat([]byte{0xaa}, 32)) rHash := sha256.Sum256(bobPreimage[:]) - bobHtlc := &lnwire.UpdateAddHTLC{ + var bobHtlc [2]*lnwire.UpdateAddHTLC + bobHtlc[0] = &lnwire.UpdateAddHTLC{ PaymentHash: rHash, Amount: htlcAmt, Expiry: uint32(10), } - bobHtlcIndex, err := bobChannel.AddHTLC(bobHtlc, nil) + bobHtlcIndex, err := bobChannel.AddHTLC(bobHtlc[0], nil) if err != nil { t.Fatalf("unable to add bob's htlc: %v", err) } - aliceHtlcIndex, err := aliceChannel.ReceiveHTLC(bobHtlc) + aliceHtlcIndex, err := aliceChannel.ReceiveHTLC(bobHtlc[0]) if err != nil { t.Fatalf("unable to recv bob's htlc: %v", err) } @@ -3297,6 +3298,49 @@ func TestChanSyncOweRevocationAndCommitForceTransition(t *testing.T) { t.Fatalf("unable to complete bob's state transition: %v", err) } + // To ensure the channel sync logic handles the case where the two + // commit chains are at different heights, we'll add another HTLC from + // Bob to Alice, but let Alice skip the commitment for this state + // update. + rHash = sha256.Sum256(bytes.Repeat([]byte{0xbb}, 32)) + bobHtlc[1] = &lnwire.UpdateAddHTLC{ + PaymentHash: rHash, + Amount: htlcAmt, + Expiry: uint32(10), + ID: 1, + } + _, err = bobChannel.AddHTLC(bobHtlc[1], nil) + if err != nil { + t.Fatalf("unable to add bob's htlc: %v", err) + } + _, err = aliceChannel.ReceiveHTLC(bobHtlc[1]) + if err != nil { + t.Fatalf("unable to recv bob's htlc: %v", err) + } + + // Bob signs the new state update, and sends the signature to Alice. + bobSig, bobHtlcSigs, err := bobChannel.SignNextCommitment() + if err != nil { + t.Fatalf("bob unable to sign commitment: %v", err) + } + + err = aliceChannel.ReceiveNewCommitment(bobSig, bobHtlcSigs) + if err != nil { + t.Fatalf("alice unable to rev bob's commitment: %v", err) + } + + // Alice revokes her current state, but doesn't immediately send a + // signature for Bob's updated state. Instead she will issue a new + // update before sending a new CommitSig. This will lead to Alice's + // local commit chain getting height > remote commit chain. + aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment() + if err != nil { + t.Fatalf("alice unable to revoke commitment: %v", err) + } + if _, _, _, err := bobChannel.ReceiveRevocation(aliceRevocation); err != nil { + t.Fatalf("bob unable to recv revocation: %v", err) + } + // Next, Alice will settle that incoming HTLC, then we'll start the // core of the test itself. err = aliceChannel.SettleHTLC(bobPreimage, aliceHtlcIndex, nil, nil, nil) @@ -3433,7 +3477,7 @@ func TestChanSyncOweRevocationAndCommitForceTransition(t *testing.T) { if err != nil { t.Fatalf("alice unable to rev bob's commitment: %v", err) } - aliceRevocation, _, err := aliceChannel.RevokeCurrentCommitment() + aliceRevocation, _, err = aliceChannel.RevokeCurrentCommitment() if err != nil { t.Fatalf("alice unable to revoke commitment: %v", err) }