Skip to content

Commit 2abe2a5

Browse files
committed
itest: fix assertions, add new test cases
1 parent a5859fd commit 2abe2a5

File tree

2 files changed

+120
-24
lines changed

2 files changed

+120
-24
lines changed

itest/assets_test.go

Lines changed: 73 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -864,8 +864,8 @@ func payInvoiceWithSatoshi(t *testing.T, payer *HarnessNode,
864864
require.NoError(t, err)
865865

866866
result, err := getPaymentResult(stream)
867-
if cfg.expectTimeout {
868-
require.ErrorContains(t, err, "context deadline exceeded")
867+
if cfg.errSubStr != "" {
868+
require.ErrorContains(t, err, cfg.errSubStr)
869869
} else {
870870
require.NoError(t, err)
871871
require.Equal(t, cfg.payStatus, result.Status)
@@ -911,17 +911,20 @@ func payInvoiceWithSatoshiLastHop(t *testing.T, payer *HarnessNode,
911911
}
912912

913913
type payConfig struct {
914-
smallShards bool
915-
expectTimeout bool
916-
payStatus lnrpc.Payment_PaymentStatus
917-
failureReason lnrpc.PaymentFailureReason
918-
rfq fn.Option[rfqmsg.ID]
914+
smallShards bool
915+
errSubStr string
916+
allowUnEconomical bool
917+
feeLimit lnwire.MilliSatoshi
918+
payStatus lnrpc.Payment_PaymentStatus
919+
failureReason lnrpc.PaymentFailureReason
920+
rfq fn.Option[rfqmsg.ID]
919921
}
920922

921923
func defaultPayConfig() *payConfig {
922924
return &payConfig{
923925
smallShards: false,
924-
expectTimeout: false,
926+
errSubStr: "",
927+
feeLimit: 1_000_000,
925928
payStatus: lnrpc.Payment_SUCCEEDED,
926929
failureReason: lnrpc.PaymentFailureReason_FAILURE_REASON_NONE,
927930
}
@@ -935,9 +938,9 @@ func withSmallShards() payOpt {
935938
}
936939
}
937940

938-
func withExpectTimeout() payOpt {
941+
func withPayErrSubStr(errSubStr string) payOpt {
939942
return func(c *payConfig) {
940-
c.expectTimeout = true
943+
c.errSubStr = errSubStr
941944
}
942945
}
943946

@@ -956,6 +959,18 @@ func withRFQ(rfqID rfqmsg.ID) payOpt {
956959
}
957960
}
958961

962+
func withFeeLimit(limit lnwire.MilliSatoshi) payOpt {
963+
return func(c *payConfig) {
964+
c.feeLimit = limit
965+
}
966+
}
967+
968+
func withAllowUnEconomical() payOpt {
969+
return func(c *payConfig) {
970+
c.allowUnEconomical = true
971+
}
972+
}
973+
959974
func payInvoiceWithAssets(t *testing.T, payer, rfqPeer *HarnessNode,
960975
payReq string, assetID []byte,
961976
opts ...payOpt) (uint64, rfqmath.BigIntFixedPoint) {
@@ -979,7 +994,7 @@ func payInvoiceWithAssets(t *testing.T, payer, rfqPeer *HarnessNode,
979994
sendReq := &routerrpc.SendPaymentRequest{
980995
PaymentRequest: payReq,
981996
TimeoutSeconds: int32(PaymentTimeout.Seconds()),
982-
FeeLimitMsat: 1_000_000,
997+
FeeLimitMsat: int64(cfg.feeLimit),
983998
}
984999

9851000
if cfg.smallShards {
@@ -993,13 +1008,24 @@ func payInvoiceWithAssets(t *testing.T, payer, rfqPeer *HarnessNode,
9931008
})
9941009

9951010
stream, err := payerTapd.SendPayment(ctxt, &tchrpc.SendPaymentRequest{
996-
AssetId: assetID,
997-
PeerPubkey: rfqPeer.PubKey[:],
998-
PaymentRequest: sendReq,
999-
RfqId: rfqBytes,
1011+
AssetId: assetID,
1012+
PeerPubkey: rfqPeer.PubKey[:],
1013+
PaymentRequest: sendReq,
1014+
RfqId: rfqBytes,
1015+
AllowUneconomical: cfg.allowUnEconomical,
10001016
})
10011017
require.NoError(t, err)
10021018

1019+
// If an error is returned by the RPC method (meaning the stream itself
1020+
// was established, no network or auth error), we expect the error to be
1021+
// returned on the first read on the stream.
1022+
if cfg.errSubStr != "" {
1023+
_, err := stream.Recv()
1024+
require.ErrorContains(t, err, cfg.errSubStr)
1025+
1026+
return 0, rfqmath.BigIntFixedPoint{}
1027+
}
1028+
10031029
var (
10041030
numUnits uint64
10051031
rateVal rfqmath.FixedPoint[rfqmath.BigInt]
@@ -1043,8 +1069,32 @@ func payInvoiceWithAssets(t *testing.T, payer, rfqPeer *HarnessNode,
10431069
return numUnits, rateVal
10441070
}
10451071

1072+
type invoiceConfig struct {
1073+
errSubStr string
1074+
}
1075+
1076+
func defaultInvoiceConfig() *invoiceConfig {
1077+
return &invoiceConfig{
1078+
errSubStr: "",
1079+
}
1080+
}
1081+
1082+
type invoiceOpt func(*invoiceConfig)
1083+
1084+
func withInvoiceErrSubStr(errSubStr string) invoiceOpt {
1085+
return func(c *invoiceConfig) {
1086+
c.errSubStr = errSubStr
1087+
}
1088+
}
1089+
10461090
func createAssetInvoice(t *testing.T, dstRfqPeer, dst *HarnessNode,
1047-
assetAmount uint64, assetID []byte) *lnrpc.AddInvoiceResponse {
1091+
assetAmount uint64, assetID []byte,
1092+
opts ...invoiceOpt) *lnrpc.AddInvoiceResponse {
1093+
1094+
cfg := defaultInvoiceConfig()
1095+
for _, opt := range opts {
1096+
opt(cfg)
1097+
}
10481098

10491099
ctxb := context.Background()
10501100
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
@@ -1068,7 +1118,13 @@ func createAssetInvoice(t *testing.T, dstRfqPeer, dst *HarnessNode,
10681118
Expiry: timeoutSeconds,
10691119
},
10701120
})
1071-
require.NoError(t, err)
1121+
if cfg.errSubStr != "" {
1122+
require.ErrorContains(t, err, cfg.errSubStr)
1123+
1124+
return nil
1125+
} else {
1126+
require.NoError(t, err)
1127+
}
10721128

10731129
decodedInvoice, err := dst.DecodePayReq(ctxt, &lnrpc.PayReqString{
10741130
PayReq: resp.InvoiceResult.PaymentRequest,

itest/litd_custom_channels_test.go

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import (
1717
"github.com/lightninglabs/taproot-assets/proof"
1818
"github.com/lightninglabs/taproot-assets/rfqmath"
1919
"github.com/lightninglabs/taproot-assets/rfqmsg"
20-
"github.com/lightninglabs/taproot-assets/tapchannel"
2120
"github.com/lightninglabs/taproot-assets/taprpc"
2221
"github.com/lightninglabs/taproot-assets/taprpc/mintrpc"
2322
oraclerpc "github.com/lightninglabs/taproot-assets/taprpc/priceoraclerpc"
@@ -1997,20 +1996,61 @@ func testCustomChannelsLiquidityEdgeCases(ctxb context.Context,
19971996
// Yara with satoshi. This is a multi-hop payment going over 2 asset
19981997
// channels, where the total asset value is less than the default anchor
19991998
// amount of 354 sats.
2000-
invoiceResp = createAssetInvoice(t.t, dave, charlie, 1, assetID)
2001-
payInvoiceWithSatoshi(t.t, yara, invoiceResp, withFailure(
2002-
lnrpc.Payment_FAILED, failureNoRoute,
1999+
createAssetInvoice(t.t, dave, charlie, 1, assetID, withInvoiceErrSubStr(
2000+
"cannot create invoice over 1 asset units, as the minimal "+
2001+
"transportable amount",
20032002
))
20042003

20052004
logBalance(t.t, nodes, assetID, "after small payment (asset "+
20062005
"invoice, <354sats)")
20072006

2007+
// Edge case: We now create a small BTC invoice on Erin and ask Charlie
2008+
// to pay it with assets. We should get a payment failure as the amount
2009+
// is too small to be paid with assets economically. But a payment is
2010+
// still possible, since the amount is large enough to represent a
2011+
// single unit (17.1 sat per unit).
2012+
btcInvoiceResp, err := erin.AddInvoice(ctxb, &lnrpc.Invoice{
2013+
Memo: "small BTC invoice",
2014+
ValueMsat: 18_000,
2015+
})
2016+
require.NoError(t.t, err)
2017+
payInvoiceWithAssets(
2018+
t.t, charlie, dave, btcInvoiceResp.PaymentRequest, assetID,
2019+
withFeeLimit(2_000), withPayErrSubStr(
2020+
"rejecting payment of 20000 mSAT",
2021+
),
2022+
)
2023+
2024+
// When we override the uneconomical payment, it should succeed.
2025+
payInvoiceWithAssets(
2026+
t.t, charlie, dave, btcInvoiceResp.PaymentRequest, assetID,
2027+
withFeeLimit(2_000), withAllowUnEconomical(),
2028+
)
2029+
logBalance(
2030+
t.t, nodes, assetID, "after small payment (BTC invoice 1 sat)",
2031+
)
2032+
2033+
// When we try to pay an invoice amount that's smaller than the
2034+
// corresponding value of a single asset unit, the payment will always
2035+
// be rejected, even if we set the allow_uneconomical flag.
2036+
btcInvoiceResp, err = erin.AddInvoice(ctxb, &lnrpc.Invoice{
2037+
Memo: "very small BTC invoice",
2038+
ValueMsat: 1_000,
2039+
})
2040+
require.NoError(t.t, err)
2041+
payInvoiceWithAssets(
2042+
t.t, charlie, dave, btcInvoiceResp.PaymentRequest, assetID,
2043+
withFeeLimit(1_000), withAllowUnEconomical(), withPayErrSubStr(
2044+
"rejecting payment of 2000 mSAT",
2045+
),
2046+
)
2047+
20082048
// Edge case: Now Dave creates an asset invoice to be paid for by
20092049
// Yara with satoshi. For the last hop we try to settle the invoice in
20102050
// satoshi, where we will check whether Dave's strict forwarding works
20112051
// as expected. Charlie is only used as a dummy RFQ peer in this case,
20122052
// Yara totally ignored the RFQ hint and pays agnostically with sats.
2013-
invoiceResp = createAssetInvoice(t.t, charlie, dave, 1, assetID)
2053+
invoiceResp = createAssetInvoice(t.t, charlie, dave, 22, assetID)
20142054

20152055
stream, err := dave.InvoicesClient.SubscribeSingleInvoice(
20162056
ctxb, &invoicesrpc.SubscribeSingleInvoiceRequest{
@@ -2164,7 +2204,7 @@ func testCustomChannelsLiquidityEdgeCases(ctxb context.Context,
21642204
// Now Erin tries to pay the invoice. Since rfq quote cannot satisfy the
21652205
// total amount of the invoice this payment will fail.
21662206
payInvoiceWithSatoshi(
2167-
t.t, erin, iResp, withExpectTimeout(),
2207+
t.t, erin, iResp, withPayErrSubStr("context deadline exceeded"),
21682208
withFailure(lnrpc.Payment_FAILED, failureNone),
21692209
)
21702210

@@ -2717,7 +2757,7 @@ func testCustomChannelsOraclePricing(_ context.Context,
27172757
commitFeeP2WSH int64 = 2810
27182758
anchorAmount int64 = 330
27192759
assetHtlcCarryAmount = int64(
2720-
tapchannel.DefaultOnChainHtlcAmount,
2760+
rfqmath.DefaultOnChainHtlcAmount,
27212761
)
27222762
unbalancedLocalAmount = channelFundingAmount - commitFeeP2TR -
27232763
anchorAmount

0 commit comments

Comments
 (0)