Skip to content

Commit e0ab462

Browse files
committed
itest: extend liquidity edge cases for rfq htlc tracking
1 parent 4bde280 commit e0ab462

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/lnrpc/walletrpc"
2831
"github.com/lightningnetwork/lnd/lntest"
2932
"github.com/lightningnetwork/lnd/lntest/port"
@@ -1805,7 +1808,7 @@ func testCustomChannelsLiquidityEdgeCases(_ context.Context,
18051808
SatPerVByte: 5,
18061809
},
18071810
)
1808-
defer closeChannelAndAssert(t, net, dave, channelOp, false)
1811+
defer closeChannelAndAssert(t, net, dave, channelOp, true)
18091812

18101813
// This is the only public channel, we need everyone to be aware of it.
18111814
assertChannelKnown(t.t, charlie, channelOp)
@@ -2020,10 +2023,11 @@ func testCustomChannelsLiquidityEdgeCases(_ context.Context,
20202023
logBalance(t.t, nodes, assetID, "after small payment (asset "+
20212024
"invoice, <354sats)")
20222025

2023-
// Edge case: Now Charlie creates an asset invoice to be paid for by
2026+
// Edge case: Now Dave creates an asset invoice to be paid for by
20242027
// Yara with satoshi. For the last hop we try to settle the invoice in
2025-
// satoshi, where we will check whether Charlie's strict forwarding
2026-
// works as expected.
2028+
// satoshi, where we will check whether Dave's strict forwarding works
2029+
// as expected. Charlie is only used as a dummy RFQ peer in this case,
2030+
// Yara totally ignored the RFQ hint and pays agnostically with sats.
20272031
invoiceResp = createAssetInvoice(
20282032
t.t, charlie, dave, 1, assetID,
20292033
)
@@ -2046,6 +2050,91 @@ func testCustomChannelsLiquidityEdgeCases(_ context.Context,
20462050

20472051
logBalance(t.t, nodes, assetID, "after failed payment (asset "+
20482052
"invoice, strict forwarding)")
2053+
2054+
// Edge case: Charlie negotiates a quote with Dave which has a low max
2055+
// amount (~170k sats). Then Charlie creates an invoice with a total
2056+
// amount slightly larger than the max allowed in the quote (200k sats).
2057+
// Erin will try to pay that invoice with sats, in shards of max size
2058+
// 80k sats. Dave will eventually stop forwarding HTLCs as the RFQ HTLC
2059+
// tracking mechanism should stop them from being forwarded, as they
2060+
// violate the maximum allowed amount of the quote.
2061+
2062+
// Charlie starts by negotiating the quote.
2063+
res, err := charlieTap.RfqClient.AddAssetBuyOrder(
2064+
ctxb, &rfqrpc.AddAssetBuyOrderRequest{
2065+
AssetSpecifier: &rfqrpc.AssetSpecifier{
2066+
Id: &rfqrpc.AssetSpecifier_AssetId{
2067+
AssetId: assetID,
2068+
},
2069+
},
2070+
AssetMaxAmt: 10_000,
2071+
Expiry: uint64(time.Now().Add(time.Hour).Unix()),
2072+
PeerPubKey: dave.PubKey[:],
2073+
TimeoutSeconds: 10,
2074+
},
2075+
)
2076+
require.NoError(t.t, err)
2077+
2078+
quote, ok := res.Response.(*rfqrpc.AddAssetBuyOrderResponse_AcceptedQuote)
2079+
require.True(t.t, ok)
2080+
2081+
// We now manually add the invoice in order to inject the above,
2082+
// manually generated, quote.
2083+
iResp, err := charlie.AddInvoice(ctxb, &lnrpc.Invoice{
2084+
Memo: "",
2085+
Value: 200_000,
2086+
RPreimage: bytes.Repeat([]byte{11}, 32),
2087+
CltvExpiry: 60,
2088+
RouteHints: []*lnrpc.RouteHint{
2089+
&lnrpc.RouteHint{
2090+
HopHints: []*lnrpc.HopHint{
2091+
&lnrpc.HopHint{
2092+
NodeId: dave.PubKeyStr,
2093+
ChanId: quote.AcceptedQuote.Scid,
2094+
},
2095+
},
2096+
},
2097+
},
2098+
})
2099+
require.NoError(t.t, err)
2100+
2101+
// Now Erin tries to pay the invoice. Since the multipart payment will
2102+
// have some of its shards failing the pathfinding logic will keep going
2103+
// and we won't see a payment failure but a timeout. If a final outcome
2104+
// is not produced within a reasonable amount of time, we assume the
2105+
// payment is still trying to find a route, therefore the HTLC rejection
2106+
// works.
2107+
timeoutChan = time.After(PaymentTimeout / 2)
2108+
done = make(chan bool, 1)
2109+
2110+
ctxc, cancel := context.WithCancel(context.Background())
2111+
2112+
//nolint:lll
2113+
go func() {
2114+
// payInvoiceWithSatoshi(t.t, erin, iResp, lnrpc.Payment_FAILED)
2115+
sendReq := &routerrpc.SendPaymentRequest{
2116+
PaymentRequest: iResp.PaymentRequest,
2117+
TimeoutSeconds: int32(PaymentTimeout.Seconds()),
2118+
MaxShardSizeMsat: 80_000_000,
2119+
FeeLimitMsat: 1_000_000,
2120+
}
2121+
stream, err := erin.RouterClient.SendPaymentV2(ctxc, sendReq)
2122+
if err == nil {
2123+
_, _ = getPaymentResult(stream)
2124+
}
2125+
2126+
done <- true
2127+
}()
2128+
2129+
select {
2130+
case <-done:
2131+
t.Fatalf("Payment should not produce a final outcome")
2132+
2133+
case <-timeoutChan:
2134+
cancel()
2135+
}
2136+
2137+
logBalance(t.t, nodes, assetID, "after htlc track")
20492138
}
20502139

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

0 commit comments

Comments
 (0)