lnwallet/test: test remote update after restart
This test asserts that remote updates that are locked-in on the local commitment, but haven't been signed for on the remote commitment, are properly restored after a restart.
This commit is contained in:
parent
41c207e247
commit
6a866890a8
@ -19,6 +19,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/input"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
|
"github.com/lightningnetwork/lnd/lntypes"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
)
|
)
|
||||||
@ -3050,6 +3051,113 @@ func TestChanSyncOweCommitment(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestChanSyncOweCommitmentPendingRemote asserts that local updates are applied
|
||||||
|
// to the remote commit across restarts.
|
||||||
|
func TestChanSyncOweCommitmentPendingRemote(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Create a test channel which will be used for the duration of this
|
||||||
|
// unittest.
|
||||||
|
aliceChannel, bobChannel, cleanUp, err := CreateTestChannels(true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to create test channels: %v", err)
|
||||||
|
}
|
||||||
|
defer cleanUp()
|
||||||
|
|
||||||
|
var fakeOnionBlob [lnwire.OnionPacketSize]byte
|
||||||
|
copy(fakeOnionBlob[:], bytes.Repeat([]byte{0x05}, lnwire.OnionPacketSize))
|
||||||
|
|
||||||
|
// We'll start off the scenario where Bob send two htlcs to Alice in a
|
||||||
|
// single state update.
|
||||||
|
var preimages []lntypes.Preimage
|
||||||
|
const numHtlcs = 2
|
||||||
|
for id := byte(0); id < numHtlcs; id++ {
|
||||||
|
htlcAmt := lnwire.NewMSatFromSatoshis(20000)
|
||||||
|
var bobPreimage [32]byte
|
||||||
|
copy(bobPreimage[:], bytes.Repeat([]byte{id}, 32))
|
||||||
|
rHash := sha256.Sum256(bobPreimage[:])
|
||||||
|
h := &lnwire.UpdateAddHTLC{
|
||||||
|
PaymentHash: rHash,
|
||||||
|
Amount: htlcAmt,
|
||||||
|
Expiry: uint32(10),
|
||||||
|
OnionBlob: fakeOnionBlob,
|
||||||
|
}
|
||||||
|
|
||||||
|
htlcIndex, err := bobChannel.AddHTLC(h, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to add bob's htlc: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
h.ID = htlcIndex
|
||||||
|
if _, err := aliceChannel.ReceiveHTLC(h); err != nil {
|
||||||
|
t.Fatalf("unable to recv bob's htlc: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
preimages = append(preimages, bobPreimage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// With the HTLCs applied to both update logs, we'll initiate a state
|
||||||
|
// transition from Bob.
|
||||||
|
if err := ForceStateTransition(bobChannel, aliceChannel); err != nil {
|
||||||
|
t.Fatalf("unable to complete bob's state transition: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next, Alice settles the HTLCs from Bob in distinct state updates.
|
||||||
|
for i := 0; i < numHtlcs; i++ {
|
||||||
|
err = aliceChannel.SettleHTLC(preimages[i], uint64(i), nil, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to settle htlc: %v", err)
|
||||||
|
}
|
||||||
|
err = bobChannel.ReceiveHTLCSettle(preimages[i], uint64(i))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to settle htlc: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
aliceSig, aliceHtlcSigs, _, err := aliceChannel.SignNextCommitment()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to sign commitment: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to receive commitment: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bob revokes his current commitment. After this call
|
||||||
|
// completes, the htlc is settled on the local commitment
|
||||||
|
// transaction. Bob still owes Alice a signature to also settle
|
||||||
|
// the htlc on her local commitment transaction.
|
||||||
|
bobRevoke, _, err := bobChannel.RevokeCurrentCommitment()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to revoke commitment: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, _, _, err = aliceChannel.ReceiveRevocation(bobRevoke)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to revoke commitment: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We restart Bob. This should have no impact on further message that
|
||||||
|
// are generated.
|
||||||
|
bobChannel, err = restartChannel(bobChannel)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to restart bob: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bob signs the commitment he owes.
|
||||||
|
_, bobHtlcSigs, _, err := bobChannel.SignNextCommitment()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to sign commitment: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This commitment is expected to contain no htlcs anymore, but because
|
||||||
|
// of a bug it is still present. THIS IS NOT CORRECT!
|
||||||
|
if len(bobHtlcSigs) != 2 {
|
||||||
|
t.Fatal("expected htlc to still be pending")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestChanSyncOweRevocation tests that if Bob restarts (and then Alice) before
|
// TestChanSyncOweRevocation tests that if Bob restarts (and then Alice) before
|
||||||
// he receiver's Alice's RevokeAndAck message, then Alice concludes that she
|
// he receiver's Alice's RevokeAndAck message, then Alice concludes that she
|
||||||
// needs to re-send the RevokeAndAck. After the revocation has been sent, both
|
// needs to re-send the RevokeAndAck. After the revocation has been sent, both
|
||||||
|
Loading…
Reference in New Issue
Block a user