lnwallet: include htlcs to settle in returned set of htlc's to forward

This commit fixes a slight bug in the channel state machine’s code
executed when processing a revocation messages. With this commit after
processing a revocation, log entries which we should forward to the
downstream or upstream peer for settling/adding HTLC’s are now properly
returned.

The testa have also been updated to ensure to correct htlc’s are
returned “for forwarding”.
This commit is contained in:
Olaoluwa Osuntokun 2016-07-16 18:12:36 -07:00
parent 2c303a1879
commit b60270f3f7
No known key found for this signature in database
GPG Key ID: 9CC5B105D03521A2
2 changed files with 41 additions and 21 deletions

@ -113,6 +113,12 @@ type PaymentDescriptor struct {
// remote party added, or one that we added locally.
Index uint32
// ParentIndex is the index of the log entry that this HTLC update
// settles or times out. If IsIncoming is false, then this refers to an
// index within our local log, otherwise this refers to an entry int he
// remote peer's log.
ParentIndex uint32
// Payload is an opaque blob which is used to complete multi-hop routing.
Payload []byte
@ -135,7 +141,7 @@ type PaymentDescriptor struct {
addCommitHeightRemote uint64
addCommitHeightLocal uint64
/// removeCommitHeight[Remote|Local] encodes the height of the
// removeCommitHeight[Remote|Local] encodes the height of the
//commitment which removed the parent pointer of this PaymentDescriptor
//either due to a timeout or a settle. Once both these heights are
//above the tail of both chains, the log entries can safely be removed.
@ -942,25 +948,32 @@ func (lc *LightningChannel) ReceiveRevocation(revMsg *lnwire.CommitRevocation) (
next = e.Next()
htlc := e.Value.(*PaymentDescriptor)
if htlc.entryType != Add {
// If this entry is either a timeout or settle, then we
// can remove it from our log once the update it locked
// into both of our chains.
if remoteChainTail >= htlc.removeCommitHeightRemote &&
localChainTail >= htlc.removeCommitHeightLocal {
parentLink := htlc.parent
lc.stateUpdateLog.Remove(e)
lc.stateUpdateLog.Remove(parentLink)
if htlc.isForwarded {
continue
}
// If this entry is either a timeout or settle, then we
// can remove it from our log once the update it locked
// into both of our chains.
if htlc.entryType != Add &&
remoteChainTail >= htlc.removeCommitHeightRemote &&
localChainTail >= htlc.removeCommitHeightLocal {
parentLink := htlc.parent
lc.stateUpdateLog.Remove(e)
lc.stateUpdateLog.Remove(parentLink)
if !htlc.IsIncoming {
htlc.ParentIndex = parentLink.Value.(*PaymentDescriptor).Index
htlcsToForward = append(htlcsToForward, htlc)
}
} else if !htlc.isForwarded {
} else if remoteChainTail >= htlc.addCommitHeightRemote &&
localChainTail >= htlc.addCommitHeightLocal {
// Once an HTLC has been fully locked into both of our
// chains, then we can safely forward it to the next
// hop.
// TODO(roasbeef): only incoming htcls?
// * re-visit once multi-hop from jcp
if remoteChainTail >= htlc.addCommitHeightRemote &&
localChainTail >= htlc.addCommitHeightLocal {
if htlc.IsIncoming {
htlc.isForwarded = true
htlcsToForward = append(htlcsToForward, htlc)
}

@ -2,7 +2,6 @@ package lnwallet
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"testing"
@ -355,13 +354,17 @@ func TestSimpleAddSettleWorkflow(t *testing.T) {
}
if htlcs, err := bobChannel.ReceiveRevocation(aliceRevocation2); err != nil {
t.Fatalf("bob unable to process alice's revocation: %v", err)
} else {
fmt.Println("bob forward htlcs: %v", htlcs)
} else if len(htlcs) != 0 {
t.Fatalf("bob shouldn't forward any HTLC's after outgoing settle, "+
"instead can forward: %v", spew.Sdump(htlcs))
}
if htlcs, err := aliceChannel.ReceiveRevocation(bobRevocation2); err != nil {
t.Fatalf("alice unable to process bob's revocation: %v", err)
} else {
fmt.Println("alice forward htlcs: %v", spew.Sdump(htlcs))
} else if len(htlcs) != 1 {
// Alice should now be able to forward the settlement HTLC to
// any down stream peers.
t.Fatalf("alice should be able to forward a single HTLC, "+
"instead can forward %v: %v", len(htlcs), spew.Sdump(htlcs))
}
// At this point, bob should have 6BTC settled, with Alice still having
@ -416,3 +419,7 @@ func TestSimpleAddSettleWorkflow(t *testing.T) {
"instead", bobLogLen)
}
}
func TestCooperativeChannelClosure(t *testing.T) {
// * add validation of their sig
}