Merge pull request #3563 from joostjager/link-test-context

htlcswitch/test: create link test context
This commit is contained in:
Johan T. Halseth 2019-10-03 09:45:36 +02:00 committed by GitHub
commit 989de44a69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 415 additions and 356 deletions

View File

@ -0,0 +1,244 @@
package htlcswitch
import (
"crypto/sha256"
"testing"
"time"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire"
)
type linkTestContext struct {
t *testing.T
aliceLink ChannelLink
bobChannel *lnwallet.LightningChannel
aliceMsgs <-chan lnwire.Message
}
// sendHtlcBobToAlice sends an HTLC from Bob to Alice, that pays to a preimage
// already in Alice's registry.
func (l *linkTestContext) sendHtlcBobToAlice(htlc *lnwire.UpdateAddHTLC) {
l.t.Helper()
_, err := l.bobChannel.AddHTLC(htlc, nil)
if err != nil {
l.t.Fatalf("bob failed adding htlc: %v", err)
}
l.aliceLink.HandleChannelUpdate(htlc)
}
// sendHtlcAliceToBob sends an HTLC from Alice to Bob, by first committing the
// HTLC in the circuit map, then delivering the outgoing packet to Alice's link.
// The HTLC will be sent to Bob via Alice's message stream.
func (l *linkTestContext) sendHtlcAliceToBob(htlcID int,
htlc *lnwire.UpdateAddHTLC) {
l.t.Helper()
circuitMap := l.aliceLink.(*channelLink).cfg.Switch.circuits
fwdActions, err := circuitMap.CommitCircuits(
&PaymentCircuit{
Incoming: CircuitKey{
HtlcID: uint64(htlcID),
},
PaymentHash: htlc.PaymentHash,
},
)
if err != nil {
l.t.Fatalf("unable to commit circuit: %v", err)
}
if len(fwdActions.Adds) != 1 {
l.t.Fatalf("expected 1 adds, found %d", len(fwdActions.Adds))
}
err = l.aliceLink.HandleSwitchPacket(&htlcPacket{
incomingHTLCID: uint64(htlcID),
htlc: htlc,
})
if err != nil {
l.t.Fatal(err)
}
}
// receiveHtlcAliceToBob pulls the next message from Alice's message stream,
// asserts that it is an UpdateAddHTLC, then applies it to Bob's state machine.
func (l *linkTestContext) receiveHtlcAliceToBob() {
l.t.Helper()
var msg lnwire.Message
select {
case msg = <-l.aliceMsgs:
case <-time.After(15 * time.Second):
l.t.Fatalf("did not received htlc from alice")
}
htlcAdd, ok := msg.(*lnwire.UpdateAddHTLC)
if !ok {
l.t.Fatalf("expected UpdateAddHTLC, got %T", msg)
}
_, err := l.bobChannel.ReceiveHTLC(htlcAdd)
if err != nil {
l.t.Fatalf("bob failed receiving htlc: %v", err)
}
}
// sendCommitSigBobToAlice makes Bob sign a new commitment and send it to
// Alice, asserting that it signs expHtlcs number of HTLCs.
func (l *linkTestContext) sendCommitSigBobToAlice(expHtlcs int) {
l.t.Helper()
sig, htlcSigs, _, err := l.bobChannel.SignNextCommitment()
if err != nil {
l.t.Fatalf("error signing commitment: %v", err)
}
commitSig := &lnwire.CommitSig{
CommitSig: sig,
HtlcSigs: htlcSigs,
}
if len(commitSig.HtlcSigs) != expHtlcs {
l.t.Fatalf("Expected %d htlc sigs, got %d", expHtlcs,
len(commitSig.HtlcSigs))
}
l.aliceLink.HandleChannelUpdate(commitSig)
}
// receiveRevAndAckAliceToBob waits for Alice to send a RevAndAck to Bob, then
// hands this to Bob.
func (l *linkTestContext) receiveRevAndAckAliceToBob() {
l.t.Helper()
var msg lnwire.Message
select {
case msg = <-l.aliceMsgs:
case <-time.After(15 * time.Second):
l.t.Fatalf("did not receive message")
}
rev, ok := msg.(*lnwire.RevokeAndAck)
if !ok {
l.t.Fatalf("expected RevokeAndAck, got %T", msg)
}
_, _, _, _, err := l.bobChannel.ReceiveRevocation(rev)
if err != nil {
l.t.Fatalf("bob failed receiving revocation: %v", err)
}
}
// receiveCommitSigAliceToBob waits for Alice to send a CommitSig to Bob,
// signing expHtlcs numbers of HTLCs, then hands this to Bob.
func (l *linkTestContext) receiveCommitSigAliceToBob(expHtlcs int) {
l.t.Helper()
var msg lnwire.Message
select {
case msg = <-l.aliceMsgs:
case <-time.After(15 * time.Second):
l.t.Fatalf("did not receive message")
}
comSig, ok := msg.(*lnwire.CommitSig)
if !ok {
l.t.Fatalf("expected CommitSig, got %T", msg)
}
if len(comSig.HtlcSigs) != expHtlcs {
l.t.Fatalf("expected %d htlc sigs, got %d", expHtlcs,
len(comSig.HtlcSigs))
}
err := l.bobChannel.ReceiveNewCommitment(comSig.CommitSig,
comSig.HtlcSigs)
if err != nil {
l.t.Fatalf("bob failed receiving commitment: %v", err)
}
}
// sendRevAndAckBobToAlice make Bob revoke his current commitment, then hand
// the RevokeAndAck to Alice.
func (l *linkTestContext) sendRevAndAckBobToAlice() {
l.t.Helper()
rev, _, err := l.bobChannel.RevokeCurrentCommitment()
if err != nil {
l.t.Fatalf("unable to revoke commitment: %v", err)
}
l.aliceLink.HandleChannelUpdate(rev)
}
// receiveSettleAliceToBob waits for Alice to send a HTLC settle message to
// Bob, then hands this to Bob.
func (l *linkTestContext) receiveSettleAliceToBob() {
l.t.Helper()
var msg lnwire.Message
select {
case msg = <-l.aliceMsgs:
case <-time.After(15 * time.Second):
l.t.Fatalf("did not receive message")
}
settleMsg, ok := msg.(*lnwire.UpdateFulfillHTLC)
if !ok {
l.t.Fatalf("expected UpdateFulfillHTLC, got %T", msg)
}
err := l.bobChannel.ReceiveHTLCSettle(settleMsg.PaymentPreimage,
settleMsg.ID)
if err != nil {
l.t.Fatalf("failed settling htlc: %v", err)
}
}
// sendSettleBobToAlice settles an HTLC on Bob's state machine, then sends an
// UpdateFulfillHTLC message to Alice's upstream inbox.
func (l *linkTestContext) sendSettleBobToAlice(htlcID uint64,
preimage lntypes.Preimage) {
l.t.Helper()
err := l.bobChannel.SettleHTLC(preimage, htlcID, nil, nil, nil)
if err != nil {
l.t.Fatalf("alice failed settling htlc id=%d hash=%x",
htlcID, sha256.Sum256(preimage[:]))
}
settle := &lnwire.UpdateFulfillHTLC{
ID: htlcID,
PaymentPreimage: preimage,
}
l.aliceLink.HandleChannelUpdate(settle)
}
// receiveSettleAliceToBob waits for Alice to send a HTLC settle message to
// Bob, then hands this to Bob.
func (l *linkTestContext) receiveFailAliceToBob() {
l.t.Helper()
var msg lnwire.Message
select {
case msg = <-l.aliceMsgs:
case <-time.After(15 * time.Second):
l.t.Fatalf("did not receive message")
}
failMsg, ok := msg.(*lnwire.UpdateFailHTLC)
if !ok {
l.t.Fatalf("expected UpdateFailHTLC, got %T", msg)
}
err := l.bobChannel.ReceiveFailHTLC(failMsg.ID, failMsg.Reason)
if err != nil {
l.t.Fatalf("unable to apply received fail htlc: %v", err)
}
}

View File

@ -4378,248 +4378,6 @@ func generateHtlcAndInvoice(t *testing.T,
return htlc, invoice
}
// sendHtlcBobToAlice sends an HTLC from Bob to Alice, that pays to a preimage
// already in Alice's registry.
func sendHtlcBobToAlice(t *testing.T, aliceLink ChannelLink,
bobChannel *lnwallet.LightningChannel, htlc *lnwire.UpdateAddHTLC) {
t.Helper()
_, err := bobChannel.AddHTLC(htlc, nil)
if err != nil {
t.Fatalf("bob failed adding htlc: %v", err)
}
aliceLink.HandleChannelUpdate(htlc)
}
// sendHtlcAliceToBob sends an HTLC from Alice to Bob, by first committing the
// HTLC in the circuit map, then delivering the outgoing packet to Alice's link.
// The HTLC will be sent to Bob via Alice's message stream.
func sendHtlcAliceToBob(t *testing.T, aliceLink ChannelLink, htlcID int,
htlc *lnwire.UpdateAddHTLC) {
t.Helper()
circuitMap := aliceLink.(*channelLink).cfg.Switch.circuits
fwdActions, err := circuitMap.CommitCircuits(
&PaymentCircuit{
Incoming: CircuitKey{
HtlcID: uint64(htlcID),
},
PaymentHash: htlc.PaymentHash,
},
)
if err != nil {
t.Fatalf("unable to commit circuit: %v", err)
}
if len(fwdActions.Adds) != 1 {
t.Fatalf("expected 1 adds, found %d", len(fwdActions.Adds))
}
aliceLink.HandleSwitchPacket(&htlcPacket{
incomingHTLCID: uint64(htlcID),
htlc: htlc,
})
}
// receiveHtlcAliceToBob pulls the next message from Alice's message stream,
// asserts that it is an UpdateAddHTLC, then applies it to Bob's state machine.
func receiveHtlcAliceToBob(t *testing.T, aliceMsgs <-chan lnwire.Message,
bobChannel *lnwallet.LightningChannel) {
t.Helper()
var msg lnwire.Message
select {
case msg = <-aliceMsgs:
case <-time.After(15 * time.Second):
t.Fatalf("did not received htlc from alice")
}
htlcAdd, ok := msg.(*lnwire.UpdateAddHTLC)
if !ok {
t.Fatalf("expected UpdateAddHTLC, got %T", msg)
}
_, err := bobChannel.ReceiveHTLC(htlcAdd)
if err != nil {
t.Fatalf("bob failed receiving htlc: %v", err)
}
}
// sendCommitSigBobToAlice makes Bob sign a new commitment and send it to
// Alice, asserting that it signs expHtlcs number of HTLCs.
func sendCommitSigBobToAlice(t *testing.T, aliceLink ChannelLink,
bobChannel *lnwallet.LightningChannel, expHtlcs int) {
t.Helper()
sig, htlcSigs, _, err := bobChannel.SignNextCommitment()
if err != nil {
t.Fatalf("error signing commitment: %v", err)
}
commitSig := &lnwire.CommitSig{
CommitSig: sig,
HtlcSigs: htlcSigs,
}
if len(commitSig.HtlcSigs) != expHtlcs {
t.Fatalf("Expected %d htlc sigs, got %d", expHtlcs,
len(commitSig.HtlcSigs))
}
aliceLink.HandleChannelUpdate(commitSig)
}
// receiveRevAndAckAliceToBob waits for Alice to send a RevAndAck to Bob, then
// hands this to Bob.
func receiveRevAndAckAliceToBob(t *testing.T, aliceMsgs chan lnwire.Message,
aliceLink ChannelLink,
bobChannel *lnwallet.LightningChannel) {
t.Helper()
var msg lnwire.Message
select {
case msg = <-aliceMsgs:
case <-time.After(15 * time.Second):
t.Fatalf("did not receive message")
}
rev, ok := msg.(*lnwire.RevokeAndAck)
if !ok {
t.Fatalf("expected RevokeAndAck, got %T", msg)
}
_, _, _, _, err := bobChannel.ReceiveRevocation(rev)
if err != nil {
t.Fatalf("bob failed receiving revocation: %v", err)
}
}
// receiveCommitSigAliceToBob waits for Alice to send a CommitSig to Bob,
// signing expHtlcs numbers of HTLCs, then hands this to Bob.
func receiveCommitSigAliceToBob(t *testing.T, aliceMsgs chan lnwire.Message,
aliceLink ChannelLink, bobChannel *lnwallet.LightningChannel,
expHtlcs int) {
t.Helper()
var msg lnwire.Message
select {
case msg = <-aliceMsgs:
case <-time.After(15 * time.Second):
t.Fatalf("did not receive message")
}
comSig, ok := msg.(*lnwire.CommitSig)
if !ok {
t.Fatalf("expected CommitSig, got %T", msg)
}
if len(comSig.HtlcSigs) != expHtlcs {
t.Fatalf("expected %d htlc sigs, got %d", expHtlcs,
len(comSig.HtlcSigs))
}
err := bobChannel.ReceiveNewCommitment(comSig.CommitSig,
comSig.HtlcSigs)
if err != nil {
t.Fatalf("bob failed receiving commitment: %v", err)
}
}
// sendRevAndAckBobToAlice make Bob revoke his current commitment, then hand
// the RevokeAndAck to Alice.
func sendRevAndAckBobToAlice(t *testing.T, aliceLink ChannelLink,
bobChannel *lnwallet.LightningChannel) {
t.Helper()
rev, _, err := bobChannel.RevokeCurrentCommitment()
if err != nil {
t.Fatalf("unable to revoke commitment: %v", err)
}
aliceLink.HandleChannelUpdate(rev)
}
// receiveSettleAliceToBob waits for Alice to send a HTLC settle message to
// Bob, then hands this to Bob.
func receiveSettleAliceToBob(t *testing.T, aliceMsgs chan lnwire.Message,
aliceLink ChannelLink, bobChannel *lnwallet.LightningChannel) {
t.Helper()
var msg lnwire.Message
select {
case msg = <-aliceMsgs:
case <-time.After(15 * time.Second):
t.Fatalf("did not receive message")
}
settleMsg, ok := msg.(*lnwire.UpdateFulfillHTLC)
if !ok {
t.Fatalf("expected UpdateFulfillHTLC, got %T", msg)
}
err := bobChannel.ReceiveHTLCSettle(settleMsg.PaymentPreimage,
settleMsg.ID)
if err != nil {
t.Fatalf("failed settling htlc: %v", err)
}
}
// sendSettleBobToAlice settles an HTLC on Bob's state machine, then sends an
// UpdateFulfillHTLC message to Alice's upstream inbox.
func sendSettleBobToAlice(t *testing.T, aliceLink ChannelLink,
bobChannel *lnwallet.LightningChannel, htlcID uint64,
preimage lntypes.Preimage) {
t.Helper()
err := bobChannel.SettleHTLC(preimage, htlcID, nil, nil, nil)
if err != nil {
t.Fatalf("alice failed settling htlc id=%d hash=%x",
htlcID, sha256.Sum256(preimage[:]))
}
settle := &lnwire.UpdateFulfillHTLC{
ID: htlcID,
PaymentPreimage: preimage,
}
aliceLink.HandleChannelUpdate(settle)
}
// receiveSettleAliceToBob waits for Alice to send a HTLC settle message to
// Bob, then hands this to Bob.
func receiveFailAliceToBob(t *testing.T, aliceMsgs chan lnwire.Message,
aliceLink ChannelLink, bobChannel *lnwallet.LightningChannel) {
t.Helper()
var msg lnwire.Message
select {
case msg = <-aliceMsgs:
case <-time.After(15 * time.Second):
t.Fatalf("did not receive message")
}
failMsg, ok := msg.(*lnwire.UpdateFailHTLC)
if !ok {
t.Fatalf("expected UpdateFailHTLC, got %T", msg)
}
err := bobChannel.ReceiveFailHTLC(failMsg.ID, failMsg.Reason)
if err != nil {
t.Fatalf("unable to apply received fail htlc: %v", err)
}
}
// TestChannelLinkNoMoreUpdates tests that we won't send a new commitment
// when there are no new updates to sign.
func TestChannelLinkNoMoreUpdates(t *testing.T) {
@ -4647,6 +4405,13 @@ func TestChannelLinkNoMoreUpdates(t *testing.T) {
htlc1 := generateHtlc(t, coreLink, bobChannel, 0)
htlc2 := generateHtlc(t, coreLink, bobChannel, 1)
ctx := linkTestContext{
t: t,
aliceLink: aliceLink,
aliceMsgs: aliceMsgs,
bobChannel: bobChannel,
}
// We now play out the following scanario:
//
// (1) Alice receives htlc1 from Bob.
@ -4677,29 +4442,29 @@ func TestChannelLinkNoMoreUpdates(t *testing.T) {
// Alice sent.
// (17) Send a signature for the empty state. No HTLCs are left.
// (18) Alice will revoke her previous state.
// Alice Bob
// | |
// | ... |
// | | <--- idle (no htlc on either side)
// | |
sendHtlcBobToAlice(t, aliceLink, bobChannel, htlc1) // |<----- add-1 ------| (1)
sendCommitSigBobToAlice(t, aliceLink, bobChannel, 1) // |<------ sig -------| (2)
sendHtlcBobToAlice(t, aliceLink, bobChannel, htlc2) // |<----- add-2 ------| (3)
receiveRevAndAckAliceToBob(t, aliceMsgs, aliceLink, bobChannel) // |------- rev ------>| (4) <--- Alice acks add-1
receiveCommitSigAliceToBob(t, aliceMsgs, aliceLink, bobChannel, 1) // |------- sig ------>| (5) <--- Alice signs add-1
sendCommitSigBobToAlice(t, aliceLink, bobChannel, 2) // |<------ sig -------| (6)
receiveRevAndAckAliceToBob(t, aliceMsgs, aliceLink, bobChannel) // |------- rev ------>| (7) <--- Alice acks add-2
sendRevAndAckBobToAlice(t, aliceLink, bobChannel) // |<------ rev -------| (8)
receiveSettleAliceToBob(t, aliceMsgs, aliceLink, bobChannel) // |------ ful-1 ----->| (9)
receiveCommitSigAliceToBob(t, aliceMsgs, aliceLink, bobChannel, 1) // |------- sig ------>| (10) <--- Alice signs add-1 + add-2 + ful-1 = add-2
sendRevAndAckBobToAlice(t, aliceLink, bobChannel) // |<------ rev -------| (11)
sendCommitSigBobToAlice(t, aliceLink, bobChannel, 1) // |<------ sig -------| (12)
receiveSettleAliceToBob(t, aliceMsgs, aliceLink, bobChannel) // |------ ful-2 ----->| (13)
receiveCommitSigAliceToBob(t, aliceMsgs, aliceLink, bobChannel, 0) // |------- sig ------>| (14) <--- Alice signs add-2 + ful-2 = no htlcs
receiveRevAndAckAliceToBob(t, aliceMsgs, aliceLink, bobChannel) // |------- rev ------>| (15)
sendRevAndAckBobToAlice(t, aliceLink, bobChannel) // |<------ rev -------| (16) <--- Bob acks that there are no more htlcs
sendCommitSigBobToAlice(t, aliceLink, bobChannel, 0) // |<------ sig -------| (17)
receiveRevAndAckAliceToBob(t, aliceMsgs, aliceLink, bobChannel) // |------- rev ------>| (18) <--- Alice acks that there are no htlcs on Alice's side
// Alice Bob
// | |
// | ... |
// | | <--- idle (no htlc on either side)
// | |
ctx.sendHtlcBobToAlice(htlc1) // |<----- add-1 ------| (1)
ctx.sendCommitSigBobToAlice(1) // |<------ sig -------| (2)
ctx.sendHtlcBobToAlice(htlc2) // |<----- add-2 ------| (3)
ctx.receiveRevAndAckAliceToBob() // |------- rev ------>| (4) <--- Alice acks add-1
ctx.receiveCommitSigAliceToBob(1) // |------- sig ------>| (5) <--- Alice signs add-1
ctx.sendCommitSigBobToAlice(2) // |<------ sig -------| (6)
ctx.receiveRevAndAckAliceToBob() // |------- rev ------>| (7) <--- Alice acks add-2
ctx.sendRevAndAckBobToAlice() // |<------ rev -------| (8)
ctx.receiveSettleAliceToBob() // |------ ful-1 ----->| (9)
ctx.receiveCommitSigAliceToBob(1) // |------- sig ------>| (10) <--- Alice signs add-1 + add-2 + ful-1 = add-2
ctx.sendRevAndAckBobToAlice() // |<------ rev -------| (11)
ctx.sendCommitSigBobToAlice(1) // |<------ sig -------| (12)
ctx.receiveSettleAliceToBob() // |------ ful-2 ----->| (13)
ctx.receiveCommitSigAliceToBob(0) // |------- sig ------>| (14) <--- Alice signs add-2 + ful-2 = no htlcs
ctx.receiveRevAndAckAliceToBob() // |------- rev ------>| (15)
ctx.sendRevAndAckBobToAlice() // |<------ rev -------| (16) <--- Bob acks that there are no more htlcs
ctx.sendCommitSigBobToAlice(0) // |<------ sig -------| (17)
ctx.receiveRevAndAckAliceToBob() // |------- rev ------>| (18) <--- Alice acks that there are no htlcs on Alice's side
// No there are no more changes to ACK or sign, make sure Alice doesn't
// attempt to send any more messages.
@ -4763,6 +4528,21 @@ func TestChannelLinkWaitForRevocation(t *testing.T) {
htlcs = append(htlcs, htlc)
}
ctx := linkTestContext{
t: t,
aliceLink: aliceLink,
aliceMsgs: aliceMsgs,
bobChannel: bobChannel,
}
assertNoMsgFromAlice := func() {
select {
case <-aliceMsgs:
t.Fatalf("did not expect message from Alice")
case <-time.After(50 * time.Millisecond):
}
}
// We play out the following scenario:
//
// (1) Add the first HTLC.
@ -4801,45 +4581,41 @@ func TestChannelLinkWaitForRevocation(t *testing.T) {
// that now. Since Bob ACKed all settles, no HTLCs should be left on
// the commitment.
// (18) Alice will revoke her previous state.
// Alice Bob
// | |
// | ... |
// | | <--- idle (no htlc on either side)
// | |
sendHtlcBobToAlice(t, aliceLink, bobChannel, htlcs[0]) // |<----- add-1 ------| (1)
sendCommitSigBobToAlice(t, aliceLink, bobChannel, 1) // |<------ sig -------| (2)
receiveRevAndAckAliceToBob(t, aliceMsgs, aliceLink, bobChannel) // |------- rev ------>| (3) <--- Alice acks add-1
receiveCommitSigAliceToBob(t, aliceMsgs, aliceLink, bobChannel, 1) // |------- sig ------>| (4) <--- Alice signs add-1
for i := 1; i < numHtlcs; i++ { // | |
sendHtlcBobToAlice(t, aliceLink, bobChannel, htlcs[i]) // |<----- add-i ------| (5.i)
sendCommitSigBobToAlice(t, aliceLink, bobChannel, i+1) // |<------ sig -------| (6.i)
receiveRevAndAckAliceToBob(t, aliceMsgs, aliceLink, bobChannel) // |------- rev ------>| (7.i) <--- Alice acks add-i
select { // | |
case <-aliceMsgs: // | | Alice should not send a sig for
t.Fatalf("unexpectedly received msg from Alice") // | | Bob's last state, since she is
default: // | | still waiting for a revocation
} // | | for the previous one.
} // | |
sendRevAndAckBobToAlice(t, aliceLink, bobChannel) // |<------ rev -------| (8) Finally let Bob send rev
receiveSettleAliceToBob(t, aliceMsgs, aliceLink, bobChannel) // |------ ful-1 ----->| (9)
receiveCommitSigAliceToBob(t, aliceMsgs, aliceLink, bobChannel, numHtlcs-1) // |------- sig ------>| (10) <--- Alice signs add-i
sendRevAndAckBobToAlice(t, aliceLink, bobChannel) // |<------ rev -------| (11)
for i := 1; i < numHtlcs; i++ { // | |
receiveSettleAliceToBob(t, aliceMsgs, aliceLink, bobChannel) // |------ ful-1 ----->| (12.i)
} // | |
sendCommitSigBobToAlice(t, aliceLink, bobChannel, numHtlcs-1) // |<------ sig -------| (13)
receiveCommitSigAliceToBob(t, aliceMsgs, aliceLink, bobChannel, 0) // |------- sig ------>| (14)
sendRevAndAckBobToAlice(t, aliceLink, bobChannel) // |<------ rev -------| (15)
receiveRevAndAckAliceToBob(t, aliceMsgs, aliceLink, bobChannel) // |------- rev ------>| (16)
sendCommitSigBobToAlice(t, aliceLink, bobChannel, 0) // |<------ sig -------| (17)
receiveRevAndAckAliceToBob(t, aliceMsgs, aliceLink, bobChannel) // |------- rev ------>| (18)
// Alice Bob
// | |
// | ... |
// | | <--- idle (no htlc on either side)
// | |
ctx.sendHtlcBobToAlice(htlcs[0]) // |<----- add-1 ------| (1)
ctx.sendCommitSigBobToAlice(1) // |<------ sig -------| (2)
ctx.receiveRevAndAckAliceToBob() // |------- rev ------>| (3) <--- Alice acks add-1
ctx.receiveCommitSigAliceToBob(1) // |------- sig ------>| (4) <--- Alice signs add-1
for i := 1; i < numHtlcs; i++ { // | |
ctx.sendHtlcBobToAlice(htlcs[i]) // |<----- add-i ------| (5.i)
ctx.sendCommitSigBobToAlice(i + 1) // |<------ sig -------| (6.i)
ctx.receiveRevAndAckAliceToBob() // |------- rev ------>| (7.i) <--- Alice acks add-i
assertNoMsgFromAlice() // | |
// | | Alice should not send a sig for
// | | Bob's last state, since she is
// | | still waiting for a revocation
// | | for the previous one.
} // | |
ctx.sendRevAndAckBobToAlice() // |<------ rev -------| (8) Finally let Bob send rev
ctx.receiveSettleAliceToBob() // |------ ful-1 ----->| (9)
ctx.receiveCommitSigAliceToBob(numHtlcs - 1) // |------- sig ------>| (10) <--- Alice signs add-i
ctx.sendRevAndAckBobToAlice() // |<------ rev -------| (11)
for i := 1; i < numHtlcs; i++ { // | |
ctx.receiveSettleAliceToBob() // |------ ful-1 ----->| (12.i)
} // | |
ctx.sendCommitSigBobToAlice(numHtlcs - 1) // |<------ sig -------| (13)
ctx.receiveCommitSigAliceToBob(0) // |------- sig ------>| (14)
ctx.sendRevAndAckBobToAlice() // |<------ rev -------| (15)
ctx.receiveRevAndAckAliceToBob() // |------- rev ------>| (16)
ctx.sendCommitSigBobToAlice(0) // |<------ sig -------| (17)
ctx.receiveRevAndAckAliceToBob() // |------- rev ------>| (18)
// Both side's state is now updated, no more messages should be sent.
select {
case <-aliceMsgs:
t.Fatalf("did not expect message from Alice")
case <-time.After(50 * time.Millisecond):
}
assertNoMsgFromAlice()
}
// TestChannelLinkBatchPreimageWrite asserts that a link will batch preimage
@ -4899,10 +4675,17 @@ func testChannelLinkBatchPreimageWrite(t *testing.T, disconnect bool) {
invoices = append(invoices, invoice)
}
ctx := linkTestContext{
t: t,
aliceLink: aliceLink,
aliceMsgs: aliceMsgs,
bobChannel: bobChannel,
}
// First, send a batch of Adds from Alice to Bob.
for i, htlc := range htlcs {
sendHtlcAliceToBob(t, aliceLink, i, htlc)
receiveHtlcAliceToBob(t, aliceMsgs, bobChannel)
ctx.sendHtlcAliceToBob(i, htlc)
ctx.receiveHtlcAliceToBob()
}
// Assert that no preimages exist for these htlcs in Alice's cache.
@ -4918,12 +4701,10 @@ func testChannelLinkBatchPreimageWrite(t *testing.T, disconnect bool) {
// Do a commitment dance to lock in the Adds, we expect numHtlcs htlcs
// to be on each party's commitment transactions.
receiveCommitSigAliceToBob(
t, aliceMsgs, aliceLink, bobChannel, numHtlcs,
)
sendRevAndAckBobToAlice(t, aliceLink, bobChannel)
sendCommitSigBobToAlice(t, aliceLink, bobChannel, numHtlcs)
receiveRevAndAckAliceToBob(t, aliceMsgs, aliceLink, bobChannel)
ctx.receiveCommitSigAliceToBob(numHtlcs)
ctx.sendRevAndAckBobToAlice()
ctx.sendCommitSigBobToAlice(numHtlcs)
ctx.receiveRevAndAckAliceToBob()
// Check again that no preimages exist for these htlcs in Alice's cache.
checkHasPreimages(t, coreLink, htlcs, false)
@ -4931,8 +4712,8 @@ func testChannelLinkBatchPreimageWrite(t *testing.T, disconnect bool) {
// Now, have Bob settle the HTLCs back to Alice using the preimages in
// the invoice corresponding to each of the HTLCs.
for i, invoice := range invoices {
sendSettleBobToAlice(
t, aliceLink, bobChannel, uint64(i),
ctx.sendSettleBobToAlice(
uint64(i),
invoice.Terms.PaymentPreimage,
)
}
@ -4953,7 +4734,7 @@ func testChannelLinkBatchPreimageWrite(t *testing.T, disconnect bool) {
// Otherwise, we are testing that Alice commits the preimages after
// receiving a CommitSig from Bob. Bob's commitment should now have 0
// HTLCs.
sendCommitSigBobToAlice(t, aliceLink, bobChannel, 0)
ctx.sendCommitSigBobToAlice(0)
// Since Alice will process the CommitSig asynchronously, we wait until
// she replies with her RevokeAndAck to ensure the tests reliably
@ -5004,6 +4785,13 @@ func TestChannelLinkCleanupSpuriousResponses(t *testing.T) {
htlc1 := generateHtlc(t, coreLink, bobChannel, 0)
htlc2 := generateHtlc(t, coreLink, bobChannel, 1)
ctx := linkTestContext{
t: t,
aliceLink: aliceLink,
aliceMsgs: aliceMsgs,
bobChannel: bobChannel,
}
// We start with he following scenario: Bob sends Alice two HTLCs, and a
// commitment dance ensures, leaving two HTLCs that Alice can respond
// to. Since Alice is in ExitSettle mode, we will then take over and
@ -5017,12 +4805,12 @@ func TestChannelLinkCleanupSpuriousResponses(t *testing.T) {
// |<----- rev ------|
// |<----- sig ------| commits add-1 + add-2
// |------ rev ----->|
sendHtlcBobToAlice(t, aliceLink, bobChannel, htlc1)
sendHtlcBobToAlice(t, aliceLink, bobChannel, htlc2)
sendCommitSigBobToAlice(t, aliceLink, bobChannel, 2)
receiveRevAndAckAliceToBob(t, aliceMsgs, aliceLink, bobChannel)
receiveCommitSigAliceToBob(t, aliceMsgs, aliceLink, bobChannel, 2)
sendRevAndAckBobToAlice(t, aliceLink, bobChannel)
ctx.sendHtlcBobToAlice(htlc1)
ctx.sendHtlcBobToAlice(htlc2)
ctx.sendCommitSigBobToAlice(2)
ctx.receiveRevAndAckAliceToBob()
ctx.receiveCommitSigAliceToBob(2)
ctx.sendRevAndAckBobToAlice()
// Give Alice to time to process the revocation.
time.Sleep(time.Second)
@ -5071,8 +4859,8 @@ func TestChannelLinkCleanupSpuriousResponses(t *testing.T) {
// Bob Alice
// |<----- fal-1 ------|
// |<----- sig ------| commits fal-1
receiveFailAliceToBob(t, aliceMsgs, aliceLink, bobChannel)
receiveCommitSigAliceToBob(t, aliceMsgs, aliceLink, bobChannel, 1)
ctx.receiveFailAliceToBob()
ctx.receiveCommitSigAliceToBob(1)
aliceFwdPkgs, err = coreLink.channel.LoadFwdPkgs()
if err != nil {
@ -5108,9 +4896,9 @@ func TestChannelLinkCleanupSpuriousResponses(t *testing.T) {
// |------ rev ----->|
// |------ sig ----->|
// |<----- rev ------|
sendRevAndAckBobToAlice(t, aliceLink, bobChannel)
sendCommitSigBobToAlice(t, aliceLink, bobChannel, 1)
receiveRevAndAckAliceToBob(t, aliceMsgs, aliceLink, bobChannel)
ctx.sendRevAndAckBobToAlice()
ctx.sendCommitSigBobToAlice(1)
ctx.receiveRevAndAckAliceToBob()
// Next, we'll construct a fail packet for add-2 (index 1), which we'll
// send to Bob and lock in. Since the AddRef is set on this instance, we
@ -5131,8 +4919,8 @@ func TestChannelLinkCleanupSpuriousResponses(t *testing.T) {
// Bob Alice
// |<----- fal-1 ------|
// |<----- sig ------| commits fal-1
receiveFailAliceToBob(t, aliceMsgs, aliceLink, bobChannel)
receiveCommitSigAliceToBob(t, aliceMsgs, aliceLink, bobChannel, 0)
ctx.receiveFailAliceToBob()
ctx.receiveCommitSigAliceToBob(0)
aliceFwdPkgs, err = coreLink.channel.LoadFwdPkgs()
if err != nil {
@ -5174,9 +4962,9 @@ func TestChannelLinkCleanupSpuriousResponses(t *testing.T) {
// |------ rev ----->|
// |------ sig ----->|
// |<----- rev ------|
sendRevAndAckBobToAlice(t, aliceLink, bobChannel)
sendCommitSigBobToAlice(t, aliceLink, bobChannel, 0)
receiveRevAndAckAliceToBob(t, aliceMsgs, aliceLink, bobChannel)
ctx.sendRevAndAckBobToAlice()
ctx.sendCommitSigBobToAlice(0)
ctx.receiveRevAndAckAliceToBob()
// We'll do a quick sanity check, and blindly send the same fail packet
// for the first HTLC. Since this HTLC index has already been settled,
@ -5381,7 +5169,12 @@ func TestChannelLinkFail(t *testing.T) {
// Generate an HTLC and send to the link.
htlc1 := generateHtlc(t, c, remoteChannel, 0)
sendHtlcBobToAlice(t, c, remoteChannel, htlc1)
ctx := linkTestContext{
t: t,
aliceLink: c,
bobChannel: remoteChannel,
}
ctx.sendHtlcBobToAlice(htlc1)
// Sign a commitment that will include
// signature for the HTLC just sent.
@ -5413,7 +5206,13 @@ func TestChannelLinkFail(t *testing.T) {
// Generate an HTLC and send to the link.
htlc1 := generateHtlc(t, c, remoteChannel, 0)
sendHtlcBobToAlice(t, c, remoteChannel, htlc1)
ctx := linkTestContext{
t: t,
aliceLink: c,
bobChannel: remoteChannel,
}
ctx.sendHtlcBobToAlice(htlc1)
// Sign a commitment that will include
// signature for the HTLC just sent.
@ -5956,12 +5755,19 @@ func TestChannelLinkHoldInvoiceRestart(t *testing.T) {
t.Fatalf("unable to add invoice to registry: %v", err)
}
ctx := linkTestContext{
t: t,
aliceLink: alice.link,
aliceMsgs: alice.msgs,
bobChannel: bobChannel,
}
// Lock in htlc paying the hodl invoice.
sendHtlcBobToAlice(t, alice.link, bobChannel, htlc)
sendCommitSigBobToAlice(t, alice.link, bobChannel, 1)
receiveRevAndAckAliceToBob(t, alice.msgs, alice.link, bobChannel)
receiveCommitSigAliceToBob(t, alice.msgs, alice.link, bobChannel, 1)
sendRevAndAckBobToAlice(t, alice.link, bobChannel)
ctx.sendHtlcBobToAlice(htlc)
ctx.sendCommitSigBobToAlice(1)
ctx.receiveRevAndAckAliceToBob()
ctx.receiveCommitSigAliceToBob(1)
ctx.sendRevAndAckBobToAlice()
// We expect a call to the invoice registry to notify the arrival of the
// htlc.
@ -5973,6 +5779,8 @@ func TestChannelLinkHoldInvoiceRestart(t *testing.T) {
// Restart link.
alice.restart(false)
ctx.aliceLink = alice.link
ctx.aliceMsgs = alice.msgs
// Expect htlc to be reprocessed.
<-registry.settleChan
@ -5981,8 +5789,8 @@ func TestChannelLinkHoldInvoiceRestart(t *testing.T) {
registry.SettleHodlInvoice(preimage)
// Expect alice to send a settle and commitsig message to bob.
receiveSettleAliceToBob(t, alice.msgs, alice.link, bobChannel)
receiveCommitSigAliceToBob(t, alice.msgs, alice.link, bobChannel, 0)
ctx.receiveSettleAliceToBob()
ctx.receiveCommitSigAliceToBob(0)
// Stop the link
alice.link.Stop()
@ -6048,12 +5856,19 @@ func TestChannelLinkRevocationWindowHodl(t *testing.T) {
t.Fatalf("unable to add invoice to registry: %v", err)
}
ctx := linkTestContext{
t: t,
aliceLink: aliceLink,
aliceMsgs: aliceMsgs,
bobChannel: bobChannel,
}
// Lock in htlc 1 on both sides.
sendHtlcBobToAlice(t, aliceLink, bobChannel, htlc1)
sendCommitSigBobToAlice(t, aliceLink, bobChannel, 1)
receiveRevAndAckAliceToBob(t, aliceMsgs, aliceLink, bobChannel)
receiveCommitSigAliceToBob(t, aliceMsgs, aliceLink, bobChannel, 1)
sendRevAndAckBobToAlice(t, aliceLink, bobChannel)
ctx.sendHtlcBobToAlice(htlc1)
ctx.sendCommitSigBobToAlice(1)
ctx.receiveRevAndAckAliceToBob()
ctx.receiveCommitSigAliceToBob(1)
ctx.sendRevAndAckBobToAlice()
// We expect a call to the invoice registry to notify the arrival of
// htlc 1.
@ -6064,11 +5879,11 @@ func TestChannelLinkRevocationWindowHodl(t *testing.T) {
}
// Lock in htlc 2 on both sides.
sendHtlcBobToAlice(t, aliceLink, bobChannel, htlc2)
sendCommitSigBobToAlice(t, aliceLink, bobChannel, 2)
receiveRevAndAckAliceToBob(t, aliceMsgs, aliceLink, bobChannel)
receiveCommitSigAliceToBob(t, aliceMsgs, aliceLink, bobChannel, 2)
sendRevAndAckBobToAlice(t, aliceLink, bobChannel)
ctx.sendHtlcBobToAlice(htlc2)
ctx.sendCommitSigBobToAlice(2)
ctx.receiveRevAndAckAliceToBob()
ctx.receiveCommitSigAliceToBob(2)
ctx.sendRevAndAckBobToAlice()
select {
case <-registry.settleChan:
@ -6081,14 +5896,14 @@ func TestChannelLinkRevocationWindowHodl(t *testing.T) {
// Expect alice to send a settle and commitsig message to bob. Bob does
// not yet send the revocation.
receiveSettleAliceToBob(t, aliceMsgs, aliceLink, bobChannel)
receiveCommitSigAliceToBob(t, aliceMsgs, aliceLink, bobChannel, 1)
ctx.receiveSettleAliceToBob()
ctx.receiveCommitSigAliceToBob(1)
// Settle invoice 2 with the preimage.
registry.SettleHodlInvoice(preimage2)
// Expect alice to send a settle for htlc 2.
receiveSettleAliceToBob(t, aliceMsgs, aliceLink, bobChannel)
ctx.receiveSettleAliceToBob()
// At this point, Alice cannot send a new commit sig to bob because the
// revocation window is exhausted.
@ -6104,7 +5919,7 @@ func TestChannelLinkRevocationWindowHodl(t *testing.T) {
}
// Bob sends revocation and signs commit with htlc 1 settled.
sendRevAndAckBobToAlice(t, aliceLink, bobChannel)
ctx.sendRevAndAckBobToAlice()
// Allow some time for it to be processed by the link.
time.Sleep(time.Second)
@ -6115,12 +5930,12 @@ func TestChannelLinkRevocationWindowHodl(t *testing.T) {
// After the revocation, it is again possible for Alice to send a commit
// sig no more htlcs. Bob acks the update.
receiveCommitSigAliceToBob(t, aliceMsgs, aliceLink, bobChannel, 0)
sendRevAndAckBobToAlice(t, aliceLink, bobChannel)
ctx.receiveCommitSigAliceToBob(0)
ctx.sendRevAndAckBobToAlice()
// Bob updates his remote commit tx.
sendCommitSigBobToAlice(t, aliceLink, bobChannel, 0)
receiveRevAndAckAliceToBob(t, aliceMsgs, aliceLink, bobChannel)
ctx.sendCommitSigBobToAlice(0)
ctx.receiveRevAndAckAliceToBob()
// Stop the link
aliceLink.Stop()