htlcswitch/link_test: generate random preimages
This commit is contained in:
parent
101ad09e9f
commit
3a186a02a9
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user