htlcswitch/link_test: generate random preimages

This commit is contained in:
Conner Fromknecht 2018-01-16 00:37:15 -08:00
parent 101ad09e9f
commit 3a186a02a9
No known key found for this signature in database
GPG Key ID: 39DE78FBE6ACB0EF
1 changed files with 215 additions and 84 deletions

View File

@ -2,7 +2,10 @@ package htlcswitch
import ( import (
"bytes" "bytes"
"crypto/rand"
"encoding/binary"
"fmt" "fmt"
"io"
"runtime" "runtime"
"strings" "strings"
"sync" "sync"
@ -837,7 +840,7 @@ func TestUpdateForwardingPolicy(t *testing.T) {
ferr, ok := err.(*ForwardingError) ferr, ok := err.(*ForwardingError)
if !ok { if !ok {
t.Fatalf("expected a ForwardingError, instead got: %T", err) t.Fatalf("expected a ForwardingError, instead got (%T): %v", err, err)
} }
switch ferr.FailureMessage.(type) { switch ferr.FailureMessage.(type) {
case *lnwire.FailFeeInsufficient: case *lnwire.FailFeeInsufficient:
@ -1050,7 +1053,11 @@ func TestChannelLinkMultiHopUnknownNextHop(t *testing.T) {
htlcAmt, totalTimelock, hops := generateHops(amount, testStartingHeight, htlcAmt, totalTimelock, hops := generateHops(amount, testStartingHeight,
n.firstBobChannelLink, n.carolChannelLink) n.firstBobChannelLink, n.carolChannelLink)
davePub := newMockServer(t, "dave").PubKey() daveServer, err := newMockServer(t, "dave", nil)
if err != nil {
t.Fatalf("unable to init dave's server: %v", err)
}
davePub := daveServer.PubKey()
receiver := n.bobServer receiver := n.bobServer
rhash, err := n.makePayment(n.aliceServer, n.bobServer, davePub, hops, rhash, err := n.makePayment(n.aliceServer, n.bobServer, davePub, hops,
amount, htlcAmt, totalTimelock).Wait(30 * time.Second) amount, htlcAmt, totalTimelock).Wait(30 * time.Second)
@ -1412,7 +1419,14 @@ func newSingleLinkTestHarness(chanAmt, chanReserve btcutil.Amount) (
}, },
} }
chanID := lnwire.NewShortChanIDFromInt(4) var chanIDBytes [8]byte
if _, err := io.ReadFull(rand.Reader, chanIDBytes[:]); err != nil {
return nil, nil, nil, nil, err
}
chanID := lnwire.NewShortChanIDFromInt(
binary.BigEndian.Uint64(chanIDBytes[:]))
aliceChannel, bobChannel, fCleanUp, _, err := createTestChannel( aliceChannel, bobChannel, fCleanUp, _, err := createTestChannel(
alicePrivKey, bobPrivKey, chanAmt, chanAmt, alicePrivKey, bobPrivKey, chanAmt, chanAmt,
chanReserve, chanReserve, chanID, chanReserve, chanReserve, chanID,
@ -1423,8 +1437,8 @@ func newSingleLinkTestHarness(chanAmt, chanReserve btcutil.Amount) (
var ( var (
invoiceRegistry = newMockRegistry() invoiceRegistry = newMockRegistry()
decoder = &mockIteratorDecoder{} decoder = newMockIteratorDecoder()
obfuscator = newMockObfuscator() obfuscator = NewMockObfuscator()
alicePeer = &mockPeer{ alicePeer = &mockPeer{
sentMsgs: make(chan lnwire.Message, 2000), sentMsgs: make(chan lnwire.Message, 2000),
quit: make(chan struct{}), quit: make(chan struct{}),
@ -1442,14 +1456,25 @@ func newSingleLinkTestHarness(chanAmt, chanReserve btcutil.Amount) (
preimageMap: make(map[[32]byte][]byte), preimageMap: make(map[[32]byte][]byte),
} }
aliceDb := aliceChannel.State().Db
aliceSwitch, err := New(Config{DB: aliceDb})
if err != nil {
return nil, nil, nil, nil, err
}
t := make(chan time.Time) t := make(chan time.Time)
ticker := &mockTicker{t} ticker := &mockTicker{t}
aliceCfg := ChannelLinkConfig{ aliceCfg := ChannelLinkConfig{
FwrdingPolicy: globalPolicy, FwrdingPolicy: globalPolicy,
Peer: alicePeer, Peer: alicePeer,
Switch: New(Config{}), Switch: aliceSwitch,
DecodeHopIterator: decoder.DecodeHopIterator, Circuits: aliceSwitch.CircuitModifier(),
DecodeOnionObfuscator: func(*sphinx.OnionPacket) (ErrorEncrypter, lnwire.FailCode) { ForwardPackets: aliceSwitch.ForwardPackets,
DecodeHopIterator: decoder.DecodeHopIterator,
DecodeHopIterators: decoder.DecodeHopIterators,
DecodeOnionObfuscator: func(*sphinx.OnionPacket) (
ErrorEncrypter, lnwire.FailCode) {
return obfuscator, lnwire.CodeNone return obfuscator, lnwire.CodeNone
}, },
GetLastChannelUpdate: mockGetChanUpdateMessage, GetLastChannelUpdate: mockGetChanUpdateMessage,
@ -1457,10 +1482,11 @@ func newSingleLinkTestHarness(chanAmt, chanReserve btcutil.Amount) (
UpdateContractSignals: func(*contractcourt.ContractSignals) error { UpdateContractSignals: func(*contractcourt.ContractSignals) error {
return nil return nil
}, },
Registry: invoiceRegistry, Registry: invoiceRegistry,
ChainEvents: &contractcourt.ChainEventSubscription{}, ChainEvents: &contractcourt.ChainEventSubscription{},
BlockEpochs: globalEpoch, BlockEpochs: globalEpoch,
BatchTicker: ticker, BatchTicker: ticker,
FwdPkgGCTicker: NewBatchTicker(time.NewTicker(5 * time.Second)),
// Make the BatchSize large enough to not // Make the BatchSize large enough to not
// trigger commit update automatically during tests. // trigger commit update automatically during tests.
BatchSize: 10000, BatchSize: 10000,
@ -1468,6 +1494,9 @@ func newSingleLinkTestHarness(chanAmt, chanReserve btcutil.Amount) (
const startingHeight = 100 const startingHeight = 100
aliceLink := NewChannelLink(aliceCfg, aliceChannel, startingHeight) aliceLink := NewChannelLink(aliceCfg, aliceChannel, startingHeight)
mailbox := newMemoryMailBox()
mailbox.Start()
aliceLink.AttachMailBox(mailbox)
if err := aliceLink.Start(); err != nil { if err := aliceLink.Start(); err != nil {
return nil, nil, nil, nil, err return nil, nil, nil, nil, err
} }
@ -1659,25 +1688,27 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
// We'll start the test by creating a single instance of // We'll start the test by creating a single instance of
const chanAmt = btcutil.SatoshiPerBitcoin * 5 const chanAmt = btcutil.SatoshiPerBitcoin * 5
link, bobChannel, tmr, cleanUp, err := newSingleLinkTestHarness(chanAmt, 0)
aliceLink, bobChannel, tmr, cleanUp, err := newSingleLinkTestHarness(chanAmt, 0)
if err != nil { if err != nil {
t.Fatalf("unable to create link: %v", err) t.Fatalf("unable to create link: %v", err)
} }
defer cleanUp() defer cleanUp()
var ( var (
carolChanID = lnwire.NewShortChanIDFromInt(3)
mockBlob [lnwire.OnionPacketSize]byte mockBlob [lnwire.OnionPacketSize]byte
aliceLink = link.(*channelLink) coreChan = aliceLink.(*channelLink).channel
aliceChannel = aliceLink.channel coreLink = aliceLink.(*channelLink)
defaultCommitFee = aliceChannel.StateSnapshot().CommitFee defaultCommitFee = coreChan.StateSnapshot().CommitFee
aliceStartingBandwidth = aliceLink.Bandwidth() aliceStartingBandwidth = aliceLink.Bandwidth()
aliceMsgs = aliceLink.cfg.Peer.(*mockPeer).sentMsgs aliceMsgs = coreLink.cfg.Peer.(*mockPeer).sentMsgs
) )
// We put Alice into HodlHTLC mode, such that she won't settle // We put Alice into HodlHTLC mode, such that she won't settle
// incoming HTLCs automatically. // incoming HTLCs automatically.
aliceLink.cfg.HodlHTLC = true coreLink.cfg.HodlHTLC = true
aliceLink.cfg.DebugHTLC = true coreLink.cfg.DebugHTLC = true
estimator := &lnwallet.StaticFeeEstimator{ estimator := &lnwallet.StaticFeeEstimator{
FeeRate: 24, FeeRate: 24,
@ -1705,9 +1736,22 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
t.Fatalf("unable to create payment: %v", err) t.Fatalf("unable to create payment: %v", err)
} }
addPkt := htlcPacket{ addPkt := htlcPacket{
htlc: htlc, htlc: htlc,
incomingChanID: sourceHop,
incomingHTLCID: 0,
obfuscator: NewMockObfuscator(),
}
circuit := makePaymentCircuit(&htlc.PaymentHash, &addPkt)
_, err = coreLink.cfg.Switch.commitCircuits(&circuit)
if err != nil {
t.Fatalf("unable to commit circuit: %v", err)
}
addPkt.circuit = &circuit
if err := aliceLink.HandleSwitchPacket(&addPkt); err != nil {
t.Fatalf("unable to handle switch packet: %v", err)
} }
aliceLink.HandleSwitchPacket(&addPkt)
time.Sleep(time.Millisecond * 500) time.Sleep(time.Millisecond * 500)
// The resulting bandwidth should reflect that Alice is paying the // The resulting bandwidth should reflect that Alice is paying the
@ -1733,10 +1777,9 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
} }
// Lock in the HTLC. // Lock in the HTLC.
if err := updateState(tmr, aliceLink, bobChannel, true); err != nil { if err := updateState(tmr, coreLink, bobChannel, true); err != nil {
t.Fatalf("unable to update state: %v", err) t.Fatalf("unable to update state: %v", err)
} }
// Locking in the HTLC should not change Alice's bandwidth. // Locking in the HTLC should not change Alice's bandwidth.
assertLinkBandwidth(t, aliceLink, aliceStartingBandwidth-htlcAmt-htlcFee) assertLinkBandwidth(t, aliceLink, aliceStartingBandwidth-htlcAmt-htlcFee)
@ -1748,7 +1791,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
t.Fatalf("unable to settle htlc: %v", err) t.Fatalf("unable to settle htlc: %v", err)
} }
htlcSettle := &lnwire.UpdateFulfillHTLC{ htlcSettle := &lnwire.UpdateFulfillHTLC{
ID: bobIndex, ID: 0,
PaymentPreimage: invoice.Terms.PaymentPreimage, PaymentPreimage: invoice.Terms.PaymentPreimage,
} }
aliceLink.HandleChannelUpdate(htlcSettle) aliceLink.HandleChannelUpdate(htlcSettle)
@ -1759,7 +1802,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
assertLinkBandwidth(t, aliceLink, aliceStartingBandwidth-htlcAmt-htlcFee) assertLinkBandwidth(t, aliceLink, aliceStartingBandwidth-htlcAmt-htlcFee)
// Lock in the settle. // Lock in the settle.
if err := updateState(tmr, aliceLink, bobChannel, false); err != nil { if err := updateState(tmr, coreLink, bobChannel, false); err != nil {
t.Fatalf("unable to update state: %v", err) t.Fatalf("unable to update state: %v", err)
} }
@ -1773,9 +1816,22 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
t.Fatalf("unable to create payment: %v", err) t.Fatalf("unable to create payment: %v", err)
} }
addPkt = htlcPacket{ addPkt = htlcPacket{
htlc: htlc, htlc: htlc,
incomingChanID: sourceHop,
incomingHTLCID: 1,
obfuscator: NewMockObfuscator(),
}
circuit = makePaymentCircuit(&htlc.PaymentHash, &addPkt)
_, err = coreLink.cfg.Switch.commitCircuits(&circuit)
if err != nil {
t.Fatalf("unable to commit circuit: %v", err)
}
addPkt.circuit = &circuit
if err := aliceLink.HandleSwitchPacket(&addPkt); err != nil {
t.Fatalf("unable to handle switch packet: %v", err)
} }
aliceLink.HandleSwitchPacket(&addPkt)
time.Sleep(time.Millisecond * 500) time.Sleep(time.Millisecond * 500)
// Again, Alice's bandwidth decreases by htlcAmt+htlcFee. // Again, Alice's bandwidth decreases by htlcAmt+htlcFee.
@ -1787,6 +1843,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
case <-time.After(2 * time.Second): case <-time.After(2 * time.Second):
t.Fatalf("did not receive message") t.Fatalf("did not receive message")
} }
addHtlc, ok = msg.(*lnwire.UpdateAddHTLC) addHtlc, ok = msg.(*lnwire.UpdateAddHTLC)
if !ok { if !ok {
t.Fatalf("expected UpdateAddHTLC, got %T", msg) t.Fatalf("expected UpdateAddHTLC, got %T", msg)
@ -1798,7 +1855,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
} }
// Lock in the HTLC, which should not affect the bandwidth. // Lock in the HTLC, which should not affect the bandwidth.
if err := updateState(tmr, aliceLink, bobChannel, true); err != nil { if err := updateState(tmr, coreLink, bobChannel, true); err != nil {
t.Fatalf("unable to update state: %v", err) t.Fatalf("unable to update state: %v", err)
} }
@ -1812,9 +1869,10 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
t.Fatalf("unable to fail htlc: %v", err) t.Fatalf("unable to fail htlc: %v", err)
} }
failMsg := &lnwire.UpdateFailHTLC{ failMsg := &lnwire.UpdateFailHTLC{
ID: bobIndex, ID: 1,
Reason: lnwire.OpaqueReason([]byte("nop")), Reason: lnwire.OpaqueReason([]byte("nop")),
} }
aliceLink.HandleChannelUpdate(failMsg) aliceLink.HandleChannelUpdate(failMsg)
time.Sleep(time.Millisecond * 500) time.Sleep(time.Millisecond * 500)
@ -1822,7 +1880,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
assertLinkBandwidth(t, aliceLink, aliceStartingBandwidth-htlcAmt*2-htlcFee) assertLinkBandwidth(t, aliceLink, aliceStartingBandwidth-htlcAmt*2-htlcFee)
// Lock in the Fail. // Lock in the Fail.
if err := updateState(tmr, aliceLink, bobChannel, false); err != nil { if err := updateState(tmr, coreLink, bobChannel, false); err != nil {
t.Fatalf("unable to update state: %v", err) t.Fatalf("unable to update state: %v", err)
} }
@ -1834,7 +1892,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
// remain unchanged (but Alice will need to pay the fee for the extra // remain unchanged (but Alice will need to pay the fee for the extra
// HTLC). // HTLC).
htlcAmt, totalTimelock, hops := generateHops(htlcAmt, testStartingHeight, htlcAmt, totalTimelock, hops := generateHops(htlcAmt, testStartingHeight,
aliceLink) coreLink)
blob, err := generateRoute(hops...) blob, err := generateRoute(hops...)
if err != nil { if err != nil {
t.Fatalf("unable to gen route: %v", err) t.Fatalf("unable to gen route: %v", err)
@ -1847,11 +1905,12 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
// We must add the invoice to the registry, such that Alice expects // We must add the invoice to the registry, such that Alice expects
// this payment. // this payment.
err = aliceLink.cfg.Registry.(*mockInvoiceRegistry).AddInvoice(*invoice) err = coreLink.cfg.Registry.(*mockInvoiceRegistry).AddInvoice(*invoice)
if err != nil { if err != nil {
t.Fatalf("unable to add invoice to registry: %v", err) t.Fatalf("unable to add invoice to registry: %v", err)
} }
htlc.ID = 0
bobIndex, err = bobChannel.AddHTLC(htlc, nil) bobIndex, err = bobChannel.AddHTLC(htlc, nil)
if err != nil { if err != nil {
t.Fatalf("unable to add htlc: %v", err) t.Fatalf("unable to add htlc: %v", err)
@ -1862,58 +1921,84 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
assertLinkBandwidth(t, aliceLink, aliceStartingBandwidth-htlcAmt) assertLinkBandwidth(t, aliceLink, aliceStartingBandwidth-htlcAmt)
// Lock in the HTLC. // Lock in the HTLC.
if err := updateState(tmr, aliceLink, bobChannel, false); err != nil { if err := updateState(tmr, coreLink, bobChannel, false); err != nil {
t.Fatalf("unable to update state: %v", err) t.Fatalf("unable to update state: %v", err)
} }
// Since Bob is adding this HTLC, Alice only needs to pay the fee. // Since Bob is adding this HTLC, Alice only needs to pay the fee.
assertLinkBandwidth(t, aliceLink, aliceStartingBandwidth-htlcAmt-htlcFee) assertLinkBandwidth(t, aliceLink, aliceStartingBandwidth-htlcAmt-htlcFee)
time.Sleep(time.Millisecond * 500)
addPkt = htlcPacket{
htlc: htlc,
incomingChanID: aliceLink.ShortChanID(),
incomingHTLCID: 0,
obfuscator: NewMockObfuscator(),
}
circuit = makePaymentCircuit(&htlc.PaymentHash, &addPkt)
_, err = coreLink.cfg.Switch.commitCircuits(&circuit)
if err != nil {
t.Fatalf("unable to commit circuit: %v", err)
}
addPkt.outgoingChanID = carolChanID
addPkt.outgoingHTLCID = 0
err = coreLink.cfg.Switch.openCircuits(addPkt.keystone())
if err != nil {
t.Fatalf("unable to set keystone: %v", err)
}
// Next, we'll settle the HTLC with our knowledge of the pre-image that // Next, we'll settle the HTLC with our knowledge of the pre-image that
// we eventually learn (simulating a multi-hop payment). The bandwidth // we eventually learn (simulating a multi-hop payment). The bandwidth
// of the channel should now be re-balanced to the starting point. // of the channel should now be re-balanced to the starting point.
settlePkt := htlcPacket{ settlePkt := htlcPacket{
incomingChanID: aliceLink.ShortChanID(),
incomingHTLCID: 0,
circuit: &circuit,
outgoingChanID: addPkt.outgoingChanID,
outgoingHTLCID: addPkt.outgoingHTLCID,
htlc: &lnwire.UpdateFulfillHTLC{ htlc: &lnwire.UpdateFulfillHTLC{
ID: bobIndex, ID: 0,
PaymentPreimage: invoice.Terms.PaymentPreimage, PaymentPreimage: invoice.Terms.PaymentPreimage,
}, },
obfuscator: NewMockObfuscator(),
} }
aliceLink.HandleSwitchPacket(&settlePkt) if err := aliceLink.HandleSwitchPacket(&settlePkt); err != nil {
t.Fatalf("unable to handle switch packet: %v", err)
}
time.Sleep(time.Millisecond * 500) time.Sleep(time.Millisecond * 500)
// Settling this HTLC gives Alice all her original bandwidth back. // Settling this HTLC gives Alice all her original bandwidth back.
assertLinkBandwidth(t, aliceLink, aliceStartingBandwidth) assertLinkBandwidth(t, aliceLink, aliceStartingBandwidth)
// Alice wil send the Settle to Bob.
select { select {
case msg = <-aliceMsgs: case msg = <-aliceMsgs:
case <-time.After(2 * time.Second): case <-time.After(2 * time.Second):
t.Fatalf("did not receive message") t.Fatalf("did not receive message")
} }
settleHtlc, ok := msg.(*lnwire.UpdateFulfillHTLC) settleMsg, ok := msg.(*lnwire.UpdateFulfillHTLC)
if !ok { if !ok {
t.Fatalf("expected UpdateFulfillHTLC, got %T", msg) t.Fatalf("expected UpdateFulfillHTLC, got %T", msg)
} }
pre := settleHtlc.PaymentPreimage err = bobChannel.ReceiveHTLCSettle(settleMsg.PaymentPreimage, settleMsg.ID)
idx := settleHtlc.ID
err = bobChannel.ReceiveHTLCSettle(pre, idx)
if err != nil { if err != nil {
t.Fatalf("unable to receive settle: %v", err) t.Fatalf("failed receiving fail htlc: %v", err)
} }
// After a settle the link should do a state transition automatically, // After failing an HTLC, the link will automatically trigger
// so we don't have to trigger it. // a state update.
if err := handleStateUpdate(aliceLink, bobChannel); err != nil { if err := handleStateUpdate(coreLink, bobChannel); err != nil {
t.Fatalf("unable to update state: %v", err) t.Fatalf("unable to update state: %v", err)
} }
assertLinkBandwidth(t, aliceLink, aliceStartingBandwidth)
// Finally, we'll test the scenario of failing an HTLC received from the // Finally, we'll test the scenario of failing an HTLC received by the
// remote node. This should result in no perceived bandwidth changes. // remote node. This should result in no perceived bandwidth changes.
htlcAmt, totalTimelock, hops = generateHops(htlcAmt, testStartingHeight, htlcAmt, totalTimelock, hops = generateHops(htlcAmt, testStartingHeight,
aliceLink) coreLink)
blob, err = generateRoute(hops...) blob, err = generateRoute(hops...)
if err != nil { if err != nil {
t.Fatalf("unable to gen route: %v", err) t.Fatalf("unable to gen route: %v", err)
@ -1922,7 +2007,8 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("unable to create payment: %v", err) t.Fatalf("unable to create payment: %v", err)
} }
if err := aliceLink.cfg.Registry.(*mockInvoiceRegistry).AddInvoice(*invoice); err != nil { err = coreLink.cfg.Registry.(*mockInvoiceRegistry).AddInvoice(*invoice)
if err != nil {
t.Fatalf("unable to add invoice to registry: %v", err) t.Fatalf("unable to add invoice to registry: %v", err)
} }
@ -1940,21 +2026,49 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
// No changes before the HTLC is locked in. // No changes before the HTLC is locked in.
assertLinkBandwidth(t, aliceLink, aliceStartingBandwidth) assertLinkBandwidth(t, aliceLink, aliceStartingBandwidth)
if err := updateState(tmr, aliceLink, bobChannel, false); err != nil { if err := updateState(tmr, coreLink, bobChannel, false); err != nil {
t.Fatalf("unable to update state: %v", err) t.Fatalf("unable to update state: %v", err)
} }
// After lock-in, Alice will have to pay the htlc fee. // After lock-in, Alice will have to pay the htlc fee.
assertLinkBandwidth(t, aliceLink, aliceStartingBandwidth-htlcFee) assertLinkBandwidth(t, aliceLink, aliceStartingBandwidth-htlcFee)
// Now fail this HTLC. addPkt = htlcPacket{
failPkt := htlcPacket{ htlc: htlc,
incomingHTLCID: bobIndex, incomingChanID: aliceLink.ShortChanID(),
htlc: &lnwire.UpdateFailHTLC{ incomingHTLCID: 1,
ID: bobIndex, obfuscator: NewMockObfuscator(),
}, }
circuit = makePaymentCircuit(&htlc.PaymentHash, &addPkt)
_, err = coreLink.cfg.Switch.commitCircuits(&circuit)
if err != nil {
t.Fatalf("unable to commit circuit: %v", err)
}
addPkt.outgoingChanID = carolChanID
addPkt.outgoingHTLCID = 1
err = coreLink.cfg.Switch.openCircuits(addPkt.keystone())
if err != nil {
t.Fatalf("unable to set keystone: %v", err)
}
failPkt := htlcPacket{
incomingChanID: aliceLink.ShortChanID(),
incomingHTLCID: 1,
circuit: &circuit,
outgoingChanID: addPkt.outgoingChanID,
outgoingHTLCID: addPkt.outgoingHTLCID,
htlc: &lnwire.UpdateFailHTLC{
ID: 1,
},
obfuscator: NewMockObfuscator(),
}
if err := aliceLink.HandleSwitchPacket(&failPkt); err != nil {
t.Fatalf("unable to handle switch packet: %v", err)
} }
aliceLink.HandleSwitchPacket(&failPkt)
time.Sleep(time.Millisecond * 500) time.Sleep(time.Millisecond * 500)
// Alice should get all her bandwidth back. // Alice should get all her bandwidth back.
@ -1977,7 +2091,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
// After failing an HTLC, the link will automatically trigger // After failing an HTLC, the link will automatically trigger
// a state update. // a state update.
if err := handleStateUpdate(aliceLink, bobChannel); err != nil { if err := handleStateUpdate(coreLink, bobChannel); err != nil {
t.Fatalf("unable to update state: %v", err) t.Fatalf("unable to update state: %v", err)
} }
assertLinkBandwidth(t, aliceLink, aliceStartingBandwidth) assertLinkBandwidth(t, aliceLink, aliceStartingBandwidth)
@ -2015,20 +2129,27 @@ func TestChannelLinkBandwidthConsistencyOverflow(t *testing.T) {
} }
feePerKw := feeRate.FeePerKWeight() feePerKw := feeRate.FeePerKWeight()
// The starting bandwidth of the channel should be exactly the amount var htlcID uint64
// that we created the channel between her and Bob. addLinkHTLC := func(id uint64, amt lnwire.MilliSatoshi) [32]byte {
expectedBandwidth := lnwire.NewMSatFromSatoshis(chanAmt - defaultCommitFee)
assertLinkBandwidth(t, aliceLink, expectedBandwidth)
addLinkHTLC := func(amt lnwire.MilliSatoshi) [32]byte {
invoice, htlc, err := generatePayment(amt, amt, 5, mockBlob) invoice, htlc, err := generatePayment(amt, amt, 5, mockBlob)
if err != nil { if err != nil {
t.Fatalf("unable to create payment: %v", err) t.Fatalf("unable to create payment: %v", err)
} }
aliceLink.HandleSwitchPacket(&htlcPacket{
htlc: htlc, addPkt := &htlcPacket{
amount: amt, htlc: htlc,
}) incomingHTLCID: id,
amount: amt,
obfuscator: NewMockObfuscator(),
}
circuit := makePaymentCircuit(&htlc.PaymentHash, addPkt)
_, err = coreLink.cfg.Switch.commitCircuits(&circuit)
if err != nil {
t.Fatalf("unable to commit circuit: %v", err)
}
addPkt.circuit = &circuit
aliceLink.HandleSwitchPacket(addPkt)
return invoice.Terms.PaymentPreimage return invoice.Terms.PaymentPreimage
} }
@ -2040,10 +2161,11 @@ func TestChannelLinkBandwidthConsistencyOverflow(t *testing.T) {
const numHTLCs = lnwallet.MaxHTLCNumber / 2 const numHTLCs = lnwallet.MaxHTLCNumber / 2
var preImages [][32]byte var preImages [][32]byte
for i := 0; i < numHTLCs; i++ { for i := 0; i < numHTLCs; i++ {
preImage := addLinkHTLC(htlcAmt) preImage := addLinkHTLC(htlcID, htlcAmt)
preImages = append(preImages, preImage) preImages = append(preImages, preImage)
totalHtlcAmt += htlcAmt totalHtlcAmt += htlcAmt
htlcID++
} }
// The HTLCs should all be sent to the remote. // The HTLCs should all be sent to the remote.
@ -2051,8 +2173,8 @@ func TestChannelLinkBandwidthConsistencyOverflow(t *testing.T) {
for i := 0; i < numHTLCs; i++ { for i := 0; i < numHTLCs; i++ {
select { select {
case msg = <-aliceMsgs: case msg = <-aliceMsgs:
case <-time.After(2 * time.Second): case <-time.After(5 * time.Second):
t.Fatalf("did not receive message") t.Fatalf("did not receive message %d", i)
} }
addHtlc, ok := msg.(*lnwire.UpdateAddHTLC) addHtlc, ok := msg.(*lnwire.UpdateAddHTLC)
@ -2078,7 +2200,7 @@ func TestChannelLinkBandwidthConsistencyOverflow(t *testing.T) {
htlcFee := lnwire.NewMSatFromSatoshis( htlcFee := lnwire.NewMSatFromSatoshis(
feePerKw.FeeForWeight(commitWeight), feePerKw.FeeForWeight(commitWeight),
) )
expectedBandwidth = aliceStartingBandwidth - totalHtlcAmt - htlcFee expectedBandwidth := aliceStartingBandwidth - totalHtlcAmt - htlcFee
expectedBandwidth += lnwire.NewMSatFromSatoshis(defaultCommitFee) expectedBandwidth += lnwire.NewMSatFromSatoshis(defaultCommitFee)
assertLinkBandwidth(t, aliceLink, expectedBandwidth) assertLinkBandwidth(t, aliceLink, expectedBandwidth)
@ -2094,10 +2216,11 @@ func TestChannelLinkBandwidthConsistencyOverflow(t *testing.T) {
// bandwidth accounting is done properly. // bandwidth accounting is done properly.
const numOverFlowHTLCs = 20 const numOverFlowHTLCs = 20
for i := 0; i < numOverFlowHTLCs; i++ { for i := 0; i < numOverFlowHTLCs; i++ {
preImage := addLinkHTLC(htlcAmt) preImage := addLinkHTLC(htlcID, htlcAmt)
preImages = append(preImages, preImage) preImages = append(preImages, preImage)
totalHtlcAmt += htlcAmt totalHtlcAmt += htlcAmt
htlcID++
} }
// No messages should be sent to the remote at this point. // No messages should be sent to the remote at this point.
@ -2245,10 +2368,18 @@ func TestChannelLinkBandwidthChanReserve(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("unable to create payment: %v", err) t.Fatalf("unable to create payment: %v", err)
} }
addPkt := htlcPacket{
htlc: htlc, addPkt := &htlcPacket{
htlc: htlc,
obfuscator: NewMockObfuscator(),
} }
aliceLink.HandleSwitchPacket(&addPkt) circuit := makePaymentCircuit(&htlc.PaymentHash, addPkt)
_, err = coreLink.cfg.Switch.commitCircuits(&circuit)
if err != nil {
t.Fatalf("unable to commit circuit: %v", err)
}
aliceLink.HandleSwitchPacket(addPkt)
time.Sleep(time.Millisecond * 100) time.Sleep(time.Millisecond * 100)
assertLinkBandwidth(t, aliceLink, aliceStartingBandwidth-htlcAmt-htlcFee) assertLinkBandwidth(t, aliceLink, aliceStartingBandwidth-htlcAmt-htlcFee)
@ -2834,11 +2965,11 @@ func TestChannelLinkUpdateCommitFee(t *testing.T) {
} }
} }
// TestChannelLinkRejectDuplicatePayment tests that if a link receives an // TestChannelLinkAcceptDuplicatePayment tests that if a link receives an
// incoming HTLC for a payment we have already settled, then it rejects the // incoming HTLC for a payment we have already settled, then it accepts the
// HTLC. We do this as we want to enforce the fact that invoices are only to be // HTLC. We do this to simplify the processing of settles after restarts or
// used _once. // failures, reducing ambiguity when a batch is only partially processed.
func TestChannelLinkRejectDuplicatePayment(t *testing.T) { func TestChannelLinkAcceptDuplicatePayment(t *testing.T) {
t.Parallel() t.Parallel()
// First, we'll create our traditional three hop network. We'll only be // First, we'll create our traditional three hop network. We'll only be
@ -2891,8 +3022,8 @@ func TestChannelLinkRejectDuplicatePayment(t *testing.T) {
// as it's a duplicate request. // as it's a duplicate request.
_, err = n.aliceServer.htlcSwitch.SendHTLC(n.bobServer.PubKey(), htlc, _, err = n.aliceServer.htlcSwitch.SendHTLC(n.bobServer.PubKey(), htlc,
newMockDeobfuscator()) newMockDeobfuscator())
if err.Error() != lnwire.CodeUnknownPaymentHash.String() { if err != nil {
t.Fatal("error haven't been received") t.Fatalf("error shouldn't have been received got: %v", err)
} }
} }