Skip to content

Commit b8e39c2

Browse files
committed
lnwallet: expand chan sync tests to cover taproot channels
In this commit, we expand some of the existing chan sync tests to cover taproot channels (the others already did). Along the way, we always assert that the `PartialSig` is populated on retransmission. In addition, we now send the new commit sig rather than the existing in-memory one to test the new logic that re-signs the commitment.
1 parent 5281998 commit b8e39c2

File tree

1 file changed

+161
-25
lines changed

1 file changed

+161
-25
lines changed

lnwallet/channel_test.go

Lines changed: 161 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3046,19 +3046,11 @@ func restartChannel(channelOld *LightningChannel) (*LightningChannel, error) {
30463046
return channelNew, nil
30473047
}
30483048

3049-
// TestChanSyncOweCommitment tests that if Bob restarts (and then Alice) before
3050-
// he receives Alice's CommitSig message, then Alice concludes that she needs
3051-
// to re-send the CommitDiff. After the diff has been sent, both nodes should
3052-
// resynchronize and be able to complete the dangling commit.
3053-
func TestChanSyncOweCommitment(t *testing.T) {
3054-
t.Parallel()
3055-
3049+
func testChanSyncOweCommitment(t *testing.T, chanType channeldb.ChannelType) {
30563050
// Create a test channel which will be used for the duration of this
30573051
// unittest. The channel will be funded evenly with Alice having 5 BTC,
30583052
// and Bob having 5 BTC.
3059-
aliceChannel, bobChannel, err := CreateTestChannels(
3060-
t, channeldb.SingleFunderTweaklessBit,
3061-
)
3053+
aliceChannel, bobChannel, err := CreateTestChannels(t, chanType)
30623054
require.NoError(t, err, "unable to create test channels")
30633055

30643056
var fakeOnionBlob [lnwire.OnionPacketSize]byte
@@ -3133,6 +3125,15 @@ func TestChanSyncOweCommitment(t *testing.T) {
31333125
aliceNewCommit, err := aliceChannel.SignNextCommitment()
31343126
require.NoError(t, err, "unable to sign commitment")
31353127

3128+
// If this is a taproot channel, then we'll generate fresh verification
3129+
// nonce for both sides.
3130+
if chanType.IsTaproot() {
3131+
_, err = aliceChannel.GenMusigNonces()
3132+
require.NoError(t, err)
3133+
_, err = bobChannel.GenMusigNonces()
3134+
require.NoError(t, err)
3135+
}
3136+
31363137
// Bob doesn't get this message so upon reconnection, they need to
31373138
// synchronize. Alice should conclude that she owes Bob a commitment,
31383139
// while Bob should think he's properly synchronized.
@@ -3144,7 +3145,7 @@ func TestChanSyncOweCommitment(t *testing.T) {
31443145
// This is a helper function that asserts Alice concludes that she
31453146
// needs to retransmit the exact commitment that we failed to send
31463147
// above.
3147-
assertAliceCommitRetransmit := func() {
3148+
assertAliceCommitRetransmit := func() *lnwire.CommitSig {
31483149
aliceMsgsToSend, _, _, err := aliceChannel.ProcessChanSyncMsg(
31493150
bobSyncMsg,
31503151
)
@@ -3209,12 +3210,25 @@ func TestChanSyncOweCommitment(t *testing.T) {
32093210
len(commitSigMsg.HtlcSigs))
32103211
}
32113212
for i, htlcSig := range commitSigMsg.HtlcSigs {
3212-
if htlcSig != aliceNewCommit.HtlcSigs[i] {
3213+
if !bytes.Equal(htlcSig.RawBytes(),
3214+
aliceNewCommit.HtlcSigs[i].RawBytes()) {
3215+
32133216
t.Fatalf("htlc sig msgs don't match: "+
3214-
"expected %x got %x",
3215-
aliceNewCommit.HtlcSigs[i], htlcSig)
3217+
"expected %v got %v",
3218+
spew.Sdump(aliceNewCommit.HtlcSigs[i]),
3219+
spew.Sdump(htlcSig))
32163220
}
32173221
}
3222+
3223+
// If this is a taproot channel, then partial sig information
3224+
// should be present in the commit sig sent over. This
3225+
// signature will be re-regenerated, so we can't compare it
3226+
// with the old one.
3227+
if chanType.IsTaproot() {
3228+
require.True(t, commitSigMsg.PartialSig.IsSome())
3229+
}
3230+
3231+
return commitSigMsg
32183232
}
32193233

32203234
// Alice should detect that she needs to re-send 5 messages: the 3
@@ -3235,14 +3249,19 @@ func TestChanSyncOweCommitment(t *testing.T) {
32353249
// send the exact same set of messages.
32363250
aliceChannel, err = restartChannel(aliceChannel)
32373251
require.NoError(t, err, "unable to restart alice")
3238-
assertAliceCommitRetransmit()
32393252

3240-
// TODO(roasbeef): restart bob as well???
3253+
// To properly simulate a restart, we'll use the *new* signature that
3254+
// would send in an actual p2p setting.
3255+
aliceReCommitSig := assertAliceCommitRetransmit()
32413256

32423257
// At this point, we should be able to resume the prior state update
32433258
// without any issues, resulting in Alice settling the 3 htlc's, and
32443259
// adding one of her own.
3245-
err = bobChannel.ReceiveNewCommitment(aliceNewCommit.CommitSigs)
3260+
err = bobChannel.ReceiveNewCommitment(&CommitSigs{
3261+
CommitSig: aliceReCommitSig.CommitSig,
3262+
HtlcSigs: aliceReCommitSig.HtlcSigs,
3263+
PartialSig: aliceReCommitSig.PartialSig,
3264+
})
32463265
require.NoError(t, err, "bob unable to process alice's commitment")
32473266
bobRevocation, _, _, err := bobChannel.RevokeCurrentCommitment()
32483267
require.NoError(t, err, "unable to revoke bob commitment")
@@ -3329,16 +3348,53 @@ func TestChanSyncOweCommitment(t *testing.T) {
33293348
}
33303349
}
33313350

3332-
// TestChanSyncOweCommitmentPendingRemote asserts that local updates are applied
3333-
// to the remote commit across restarts.
3334-
func TestChanSyncOweCommitmentPendingRemote(t *testing.T) {
3351+
// TestChanSyncOweCommitment tests that if Bob restarts (and then Alice) before
3352+
// he receives Alice's CommitSig message, then Alice concludes that she needs
3353+
// to re-send the CommitDiff. After the diff has been sent, both nodes should
3354+
// resynchronize and be able to complete the dangling commit.
3355+
func TestChanSyncOweCommitment(t *testing.T) {
33353356
t.Parallel()
33363357

3358+
testCases := []struct {
3359+
name string
3360+
chanType channeldb.ChannelType
3361+
}{
3362+
{
3363+
name: "tweakless",
3364+
chanType: channeldb.SingleFunderTweaklessBit,
3365+
},
3366+
{
3367+
name: "anchors",
3368+
chanType: channeldb.SingleFunderTweaklessBit |
3369+
channeldb.AnchorOutputsBit,
3370+
},
3371+
{
3372+
name: "taproot",
3373+
chanType: channeldb.SingleFunderTweaklessBit |
3374+
channeldb.AnchorOutputsBit |
3375+
channeldb.SimpleTaprootFeatureBit,
3376+
},
3377+
{
3378+
name: "taproot with tapscript root",
3379+
chanType: channeldb.SingleFunderTweaklessBit |
3380+
channeldb.AnchorOutputsBit |
3381+
channeldb.SimpleTaprootFeatureBit |
3382+
channeldb.TapscriptRootBit,
3383+
},
3384+
}
3385+
for _, tc := range testCases {
3386+
t.Run(tc.name, func(t *testing.T) {
3387+
testChanSyncOweCommitment(t, tc.chanType)
3388+
})
3389+
}
3390+
}
3391+
3392+
func testChanSyncOweCommitmentPendingRemote(t *testing.T,
3393+
chanType channeldb.ChannelType) {
3394+
33373395
// Create a test channel which will be used for the duration of this
33383396
// unittest.
3339-
aliceChannel, bobChannel, err := CreateTestChannels(
3340-
t, channeldb.SingleFunderTweaklessBit,
3341-
)
3397+
aliceChannel, bobChannel, err := CreateTestChannels(t, chanType)
33423398
require.NoError(t, err, "unable to create test channels")
33433399

33443400
var fakeOnionBlob [lnwire.OnionPacketSize]byte
@@ -3421,6 +3477,12 @@ func TestChanSyncOweCommitmentPendingRemote(t *testing.T) {
34213477
bobChannel, err = restartChannel(bobChannel)
34223478
require.NoError(t, err, "unable to restart bob")
34233479

3480+
// If this is a taproot channel, then since Bob just restarted, we need
3481+
// to exchange nonces once again.
3482+
if chanType.IsTaproot() {
3483+
require.NoError(t, initMusigNonce(aliceChannel, bobChannel))
3484+
}
3485+
34243486
// Bob signs the commitment he owes.
34253487
bobNewCommit, err := bobChannel.SignNextCommitment()
34263488
require.NoError(t, err, "unable to sign commitment")
@@ -3446,6 +3508,45 @@ func TestChanSyncOweCommitmentPendingRemote(t *testing.T) {
34463508
}
34473509
}
34483510

3511+
// TestChanSyncOweCommitmentPendingRemote asserts that local updates are applied
3512+
// to the remote commit across restarts.
3513+
func TestChanSyncOweCommitmentPendingRemote(t *testing.T) {
3514+
t.Parallel()
3515+
3516+
testCases := []struct {
3517+
name string
3518+
chanType channeldb.ChannelType
3519+
}{
3520+
{
3521+
name: "tweakless",
3522+
chanType: channeldb.SingleFunderTweaklessBit,
3523+
},
3524+
{
3525+
name: "anchors",
3526+
chanType: channeldb.SingleFunderTweaklessBit |
3527+
channeldb.AnchorOutputsBit,
3528+
},
3529+
{
3530+
name: "taproot",
3531+
chanType: channeldb.SingleFunderTweaklessBit |
3532+
channeldb.AnchorOutputsBit |
3533+
channeldb.SimpleTaprootFeatureBit,
3534+
},
3535+
{
3536+
name: "taproot with tapscript root",
3537+
chanType: channeldb.SingleFunderTweaklessBit |
3538+
channeldb.AnchorOutputsBit |
3539+
channeldb.SimpleTaprootFeatureBit |
3540+
channeldb.TapscriptRootBit,
3541+
},
3542+
}
3543+
for _, tc := range testCases {
3544+
t.Run(tc.name, func(t *testing.T) {
3545+
testChanSyncOweCommitmentPendingRemote(t, tc.chanType)
3546+
})
3547+
}
3548+
}
3549+
34493550
// testChanSyncOweRevocation is the internal version of
34503551
// TestChanSyncOweRevocation that is parameterized based on the type of channel
34513552
// being used in the test.
@@ -3595,8 +3696,6 @@ func testChanSyncOweRevocation(t *testing.T, chanType channeldb.ChannelType) {
35953696

35963697
assertAliceOwesRevoke()
35973698

3598-
// TODO(roasbeef): restart bob too???
3599-
36003699
// We'll continue by then allowing bob to process Alice's revocation
36013700
// message.
36023701
_, _, _, _, err = bobChannel.ReceiveRevocation(aliceRevocation)
@@ -3645,6 +3744,15 @@ func TestChanSyncOweRevocation(t *testing.T) {
36453744

36463745
testChanSyncOweRevocation(t, taprootBits)
36473746
})
3747+
t.Run("taproot with tapscript root", func(t *testing.T) {
3748+
taprootBits := channeldb.SimpleTaprootFeatureBit |
3749+
channeldb.AnchorOutputsBit |
3750+
channeldb.ZeroHtlcTxFeeBit |
3751+
channeldb.SingleFunderTweaklessBit |
3752+
channeldb.TapscriptRootBit
3753+
3754+
testChanSyncOweRevocation(t, taprootBits)
3755+
})
36483756
}
36493757

36503758
func testChanSyncOweRevocationAndCommit(t *testing.T,
@@ -3774,6 +3882,14 @@ func testChanSyncOweRevocationAndCommit(t *testing.T,
37743882
bobNewCommit.HtlcSigs[i])
37753883
}
37763884
}
3885+
3886+
// If this is a taproot channel, then partial sig information
3887+
// should be present in the commit sig sent over. This
3888+
// signature will be re-regenerated, so we can't compare it
3889+
// with the old one.
3890+
if chanType.IsTaproot() {
3891+
require.True(t, bobReCommitSigMsg.PartialSig.IsSome())
3892+
}
37773893
}
37783894

37793895
// We expect Bob to send exactly two messages: first his revocation
@@ -3830,6 +3946,15 @@ func TestChanSyncOweRevocationAndCommit(t *testing.T) {
38303946

38313947
testChanSyncOweRevocationAndCommit(t, taprootBits)
38323948
})
3949+
t.Run("taproot with tapscript root", func(t *testing.T) {
3950+
taprootBits := channeldb.SimpleTaprootFeatureBit |
3951+
channeldb.AnchorOutputsBit |
3952+
channeldb.ZeroHtlcTxFeeBit |
3953+
channeldb.SingleFunderTweaklessBit |
3954+
channeldb.TapscriptRootBit
3955+
3956+
testChanSyncOweRevocationAndCommit(t, taprootBits)
3957+
})
38333958
}
38343959

38353960
func testChanSyncOweRevocationAndCommitForceTransition(t *testing.T,
@@ -4061,6 +4186,17 @@ func TestChanSyncOweRevocationAndCommitForceTransition(t *testing.T) {
40614186
t, taprootBits,
40624187
)
40634188
})
4189+
t.Run("taproot with tapscript root", func(t *testing.T) {
4190+
taprootBits := channeldb.SimpleTaprootFeatureBit |
4191+
channeldb.AnchorOutputsBit |
4192+
channeldb.ZeroHtlcTxFeeBit |
4193+
channeldb.SingleFunderTweaklessBit |
4194+
channeldb.TapscriptRootBit
4195+
4196+
testChanSyncOweRevocationAndCommitForceTransition(
4197+
t, taprootBits,
4198+
)
4199+
})
40644200
}
40654201

40664202
// TestChanSyncFailure tests the various scenarios during channel sync where we

0 commit comments

Comments
 (0)