lnwallet: add new TestNewBreachRetributionSkipsDustHtlcs test

This commit is contained in:
Olaoluwa Osuntokun 2018-04-05 16:20:16 -07:00
parent f79af461d3
commit 7da8cb2910
No known key found for this signature in database
GPG Key ID: 964EA263DD637C21

@ -5012,3 +5012,98 @@ func TestMinHTLC(t *testing.T) {
t.Fatalf("expected ErrBelowMinHTLC, instead received: %v", err)
}
}
// TestNewBreachRetributionSkipsDustHtlcs ensures that in the case of a
// contract breach, all dust HTLCs are ignored and not reflected in the
// produced BreachRetribution struct. We ignore these HTLCs as they aren't
// actually manifested on the commitment transaction, as a result we can't
// actually revoked them.
func TestNewBreachRetributionSkipsDustHtlcs(t *testing.T) {
t.Parallel()
// We'll kick off the test by creating our channels which both are
// loaded with 5 BTC each.
aliceChannel, bobChannel, cleanUp, err := createTestChannels(1)
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 modify the dust settings on both channels to be a predictable
// value for the prurpose of the test.
dustValue := btcutil.Amount(200)
aliceChannel.channelState.LocalChanCfg.DustLimit = dustValue
aliceChannel.channelState.RemoteChanCfg.DustLimit = dustValue
bobChannel.channelState.LocalChanCfg.DustLimit = dustValue
bobChannel.channelState.RemoteChanCfg.DustLimit = dustValue
// We'll now create a series of dust HTLC's, and send then from Alice
// to Bob, finally locking both of them in.
var bobPreimage [32]byte
copy(bobPreimage[:], bytes.Repeat([]byte{0xbb}, 32))
for i := 0; i < 3; i++ {
rHash := sha256.Sum256(bobPreimage[:])
h := &lnwire.UpdateAddHTLC{
PaymentHash: rHash,
Amount: lnwire.NewMSatFromSatoshis(dustValue),
Expiry: uint32(10),
OnionBlob: fakeOnionBlob,
}
htlcIndex, err := aliceChannel.AddHTLC(h, nil)
if err != nil {
t.Fatalf("unable to add bob's htlc: %v", err)
}
h.ID = htlcIndex
if _, err := bobChannel.ReceiveHTLC(h); err != nil {
t.Fatalf("unable to recv bob's htlc: %v", err)
}
}
// With the HTLC's applied to both update logs, we'll initiate a state
// transition from Alice.
if err := forceStateTransition(bobChannel, aliceChannel); err != nil {
t.Fatalf("unable to complete bob's state transition: %v", err)
}
// At this point, we'll capture the current state number, as well as
// the current commitment.
revokedCommit := bobChannel.channelState.LocalCommitment.CommitTx
revokedStateNum := aliceChannel.channelState.LocalCommitment.CommitHeight
// We'll now have Bob settle those HTLC's to Alice and then advance
// forward to a new state.
for i := 0; i < 3; i++ {
err := bobChannel.SettleHTLC(bobPreimage, uint64(i), nil, nil, nil)
if err != nil {
t.Fatalf("unable to settle htlc: %v", err)
}
err = aliceChannel.ReceiveHTLCSettle(bobPreimage, uint64(i))
if err != nil {
t.Fatalf("unable to settle htlc: %v", err)
}
}
if err := forceStateTransition(bobChannel, aliceChannel); err != nil {
t.Fatalf("unable to complete bob's state transition: %v", err)
}
// At this point, we'll now simulate a contract breach by Bob using the
// NewBreachRetribution method.
breachRet, err := NewBreachRetribution(
aliceChannel.channelState, revokedStateNum, revokedCommit, 100,
)
if err != nil {
t.Fatalf("unable to create breach retribution: %v", err)
}
// The retribution shouldn't have any HTLCs set as they were all below
// dust for both parties.
if len(breachRet.HtlcRetributions) != 0 {
t.Fatalf("zero HTLC retributions should have been created, "+
"instead %v were", len(breachRet.HtlcRetributions))
}
}