Skip to content

Commit 6b56147

Browse files
committed
itest: extend liquidity edge cases for rfq htlc tracking
1 parent 160ea8f commit 6b56147

File tree

1 file changed

+93
-4
lines changed

1 file changed

+93
-4
lines changed

itest/litd_custom_channels_test.go

Lines changed: 93 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package itest
22

33
import (
4+
"bytes"
45
"context"
56
"fmt"
67
"math"
@@ -18,12 +19,14 @@ import (
1819
"github.com/lightninglabs/taproot-assets/tapchannel"
1920
"github.com/lightninglabs/taproot-assets/taprpc"
2021
"github.com/lightninglabs/taproot-assets/taprpc/mintrpc"
22+
"github.com/lightninglabs/taproot-assets/taprpc/rfqrpc"
2123
tchrpc "github.com/lightninglabs/taproot-assets/taprpc/tapchannelrpc"
2224
"github.com/lightninglabs/taproot-assets/taprpc/universerpc"
2325
"github.com/lightninglabs/taproot-assets/tapscript"
2426
"github.com/lightningnetwork/lnd/fn"
2527
"github.com/lightningnetwork/lnd/lnrpc"
2628
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
29+
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
2730
"github.com/lightningnetwork/lnd/lntest"
2831
"github.com/lightningnetwork/lnd/lntest/port"
2932
"github.com/lightningnetwork/lnd/lntest/wait"
@@ -1766,7 +1769,7 @@ func testCustomChannelsLiquidityEdgeCases(_ context.Context,
17661769
SatPerVByte: 5,
17671770
},
17681771
)
1769-
defer closeChannelAndAssert(t, net, dave, channelOp, false)
1772+
defer closeChannelAndAssert(t, net, dave, channelOp, true)
17701773

17711774
// This is the only public channel, we need everyone to be aware of it.
17721775
assertChannelKnown(t.t, charlie, channelOp)
@@ -1974,10 +1977,11 @@ func testCustomChannelsLiquidityEdgeCases(_ context.Context,
19741977
logBalance(t.t, nodes, assetID, "after small payment (asset "+
19751978
"invoice, <354sats)")
19761979

1977-
// Edge case: Now Charlie creates an asset invoice to be paid for by
1980+
// Edge case: Now Dave creates an asset invoice to be paid for by
19781981
// Yara with satoshi. For the last hop we try to settle the invoice in
1979-
// satoshi, where we will check whether Charlie's strict forwarding
1980-
// works as expected.
1982+
// satoshi, where we will check whether Dave's strict forwarding works
1983+
// as expected. Charlie is only used as a dummy RFQ peer in this case,
1984+
// Yara totally ignored the RFQ hint and pays agnostically with sats.
19811985
invoiceResp = createAssetInvoice(
19821986
t.t, charlie, dave, 1, assetID,
19831987
)
@@ -2000,6 +2004,91 @@ func testCustomChannelsLiquidityEdgeCases(_ context.Context,
20002004

20012005
logBalance(t.t, nodes, assetID, "after failed payment (asset "+
20022006
"invoice, strict forwarding)")
2007+
2008+
// Edge case: Charlie negotiates a quote with Dave which has a low max
2009+
// amount (~170k sats). Then Charlie creates an invoice with a total
2010+
// amount slightly larger than the max allowed in the quote (200k sats).
2011+
// Erin will try to pay that invoice with sats, in shards of max size
2012+
// 80k sats. Dave will eventually stop forwarding HTLCs as the RFQ HTLC
2013+
// tracking mechanism should stop them from being forwarded, as they
2014+
// violate the maximum allowed amount of the quote.
2015+
2016+
// Charlie starts by negotiating the quote.
2017+
res, err := charlieTap.RfqClient.AddAssetBuyOrder(
2018+
ctxb, &rfqrpc.AddAssetBuyOrderRequest{
2019+
AssetSpecifier: &rfqrpc.AssetSpecifier{
2020+
Id: &rfqrpc.AssetSpecifier_AssetId{
2021+
AssetId: assetID,
2022+
},
2023+
},
2024+
AssetMaxAmt: 10_000,
2025+
Expiry: uint64(time.Now().Add(time.Hour).Unix()),
2026+
PeerPubKey: dave.PubKey[:],
2027+
TimeoutSeconds: 10,
2028+
},
2029+
)
2030+
require.NoError(t.t, err)
2031+
2032+
quote, ok := res.Response.(*rfqrpc.AddAssetBuyOrderResponse_AcceptedQuote)
2033+
require.True(t.t, ok)
2034+
2035+
// We now manually add the invoice in order to inject the above,
2036+
// manually generated, quote.
2037+
iResp, err := charlie.AddInvoice(ctxb, &lnrpc.Invoice{
2038+
Memo: "",
2039+
Value: 200_000,
2040+
RPreimage: bytes.Repeat([]byte{11}, 32),
2041+
CltvExpiry: 60,
2042+
RouteHints: []*lnrpc.RouteHint{
2043+
&lnrpc.RouteHint{
2044+
HopHints: []*lnrpc.HopHint{
2045+
&lnrpc.HopHint{
2046+
NodeId: dave.PubKeyStr,
2047+
ChanId: quote.AcceptedQuote.Scid,
2048+
},
2049+
},
2050+
},
2051+
},
2052+
})
2053+
require.NoError(t.t, err)
2054+
2055+
// Now Erin tries to pay the invoice. Since the multipart payment will
2056+
// have some of its shards failing the pathfinding logic will keep going
2057+
// and we won't see a payment failure but a timeout. If a final outcome
2058+
// is not produced within a reasonable amount of time, we assume the
2059+
// payment is still trying to find a route, therefore the HTLC rejection
2060+
// works.
2061+
timeoutChan = time.After(PaymentTimeout / 2)
2062+
done = make(chan bool, 1)
2063+
2064+
ctxc, cancel := context.WithCancel(context.Background())
2065+
2066+
//nolint:lll
2067+
go func() {
2068+
// payInvoiceWithSatoshi(t.t, erin, iResp, lnrpc.Payment_FAILED)
2069+
sendReq := &routerrpc.SendPaymentRequest{
2070+
PaymentRequest: iResp.PaymentRequest,
2071+
TimeoutSeconds: int32(PaymentTimeout.Seconds()),
2072+
MaxShardSizeMsat: 80_000_000,
2073+
FeeLimitMsat: 1_000_000,
2074+
}
2075+
stream, err := erin.RouterClient.SendPaymentV2(ctxc, sendReq)
2076+
if err == nil {
2077+
_, _ = getPaymentResult(stream)
2078+
}
2079+
2080+
done <- true
2081+
}()
2082+
2083+
select {
2084+
case <-done:
2085+
t.Fatalf("Payment should not produce a final outcome")
2086+
2087+
case <-timeoutChan:
2088+
cancel()
2089+
}
2090+
2091+
logBalance(t.t, nodes, assetID, "after htlc track")
20032092
}
20042093

20052094
// testCustomChannelsBalanceConsistency is a test that test the balance of nodes

0 commit comments

Comments
 (0)