Skip to content

Commit 3041f1e

Browse files
committed
itest: assert invoice and payment HTLCs show custom data
With this commit we sporadically assert in our itests that the outgoing HTLCs for a payment and the incoming HTLCs of an invoice show the custom channel data JSON with the actual asset amounts.
1 parent d5262c4 commit 3041f1e

File tree

2 files changed

+129
-5
lines changed

2 files changed

+129
-5
lines changed

itest/assets_test.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"github.com/lightninglabs/taproot-assets/tapscript"
3434
"github.com/lightningnetwork/lnd/fn"
3535
"github.com/lightningnetwork/lnd/lnrpc"
36+
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
3637
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
3738
"github.com/lightningnetwork/lnd/lntest/rpc"
3839
"github.com/lightningnetwork/lnd/lntest/wait"
@@ -838,6 +839,88 @@ func createAssetInvoice(t *testing.T, dstRfqPeer, dst *HarnessNode,
838839
return resp.InvoiceResult
839840
}
840841

842+
// assertInvoiceHtlcAssets makes sure the invoice with the given hash shows the
843+
// individual HTLCs that arrived for it and that they show the correct asset
844+
// amounts when decoded.
845+
func assertInvoiceHtlcAssets(t *testing.T, node *HarnessNode,
846+
addedInvoice *lnrpc.AddInvoiceResponse, assetAmount uint64) {
847+
848+
ctxb := context.Background()
849+
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
850+
defer cancel()
851+
852+
invoice, err := node.InvoicesClient.LookupInvoiceV2(
853+
ctxt, &invoicesrpc.LookupInvoiceMsg{
854+
InvoiceRef: &invoicesrpc.LookupInvoiceMsg_PaymentAddr{
855+
PaymentAddr: addedInvoice.PaymentAddr,
856+
},
857+
},
858+
)
859+
require.NoError(t, err)
860+
require.NotEmpty(t, invoice.Htlcs)
861+
862+
t.Logf("Asset invoice: %v", toProtoJSON(t, invoice))
863+
864+
var totalAssetAmount uint64
865+
for _, htlc := range invoice.Htlcs {
866+
require.NotEmpty(t, htlc.CustomChannelData)
867+
868+
jsonHtlc := &rfqmsg.JsonHtlc{}
869+
err := json.Unmarshal(htlc.CustomChannelData, jsonHtlc)
870+
require.NoError(t, err)
871+
872+
for _, balance := range jsonHtlc.Balances {
873+
totalAssetAmount += balance.Amount
874+
}
875+
}
876+
877+
// Due to rounding we allow up to 1 unit of error.
878+
require.InDelta(t, assetAmount, totalAssetAmount, 1)
879+
}
880+
881+
// assertPaymentHtlcAssets makes sure the payment with the given hash shows the
882+
// individual HTLCs that arrived for it and that they show the correct asset
883+
// amounts when decoded.
884+
func assertPaymentHtlcAssets(t *testing.T, node *HarnessNode, payHash []byte,
885+
assetAmount uint64) {
886+
887+
ctxb := context.Background()
888+
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
889+
defer cancel()
890+
891+
stream, err := node.RouterClient.TrackPaymentV2(
892+
ctxt, &routerrpc.TrackPaymentRequest{
893+
PaymentHash: payHash,
894+
NoInflightUpdates: true,
895+
},
896+
)
897+
require.NoError(t, err)
898+
899+
payment, err := stream.Recv()
900+
require.NoError(t, err)
901+
require.NotNil(t, payment)
902+
require.NotEmpty(t, payment.Htlcs)
903+
904+
t.Logf("Asset payment: %v", toProtoJSON(t, payment))
905+
906+
var totalAssetAmount uint64
907+
for _, htlc := range payment.Htlcs {
908+
require.NotNil(t, htlc.Route)
909+
require.NotEmpty(t, htlc.Route.CustomChannelData)
910+
911+
jsonHtlc := &rfqmsg.JsonHtlc{}
912+
err := json.Unmarshal(htlc.Route.CustomChannelData, jsonHtlc)
913+
require.NoError(t, err)
914+
915+
for _, balance := range jsonHtlc.Balances {
916+
totalAssetAmount += balance.Amount
917+
}
918+
}
919+
920+
// Due to rounding we allow up to 1 unit of error.
921+
require.InDelta(t, assetAmount, totalAssetAmount, 1)
922+
}
923+
841924
func waitForSendEvent(t *testing.T,
842925
sendEvents taprpc.TaprootAssets_SubscribeSendEventsClient,
843926
expectedState tapfreighter.SendState) {

itest/litd_custom_channels_test.go

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,16 @@ func testCustomChannelsLarge(_ context.Context, net *NetworkHarness,
234234
payInvoiceWithAssets(t.t, charlie, dave, invoiceResp3, assetID, false)
235235
logBalance(t.t, nodes, assetID, "after invoice 3")
236236

237+
// Make sure the invoice on the receiver side and the payment on the
238+
// sender side show the individual HTLCs that arrived for it and that
239+
// they show the correct asset amounts when decoded.
240+
assertInvoiceHtlcAssets(
241+
t.t, dave, invoiceResp3, largeInvoiceAmount,
242+
)
243+
assertPaymentHtlcAssets(
244+
t.t, charlie, invoiceResp3.RHash, largeInvoiceAmount,
245+
)
246+
237247
// We keysend the rest, so that all the balance is on Dave's side.
238248
charlieRemainingBalance := charlieFundingAmount - largeInvoiceAmount -
239249
fabiaInvoiceAssetAmount/2
@@ -420,6 +430,16 @@ func testCustomChannels(_ context.Context, net *NetworkHarness,
420430
payInvoiceWithAssets(t.t, dave, charlie, invoiceResp, assetID, true)
421431
logBalance(t.t, nodes, assetID, "after invoice back")
422432

433+
// Make sure the invoice on the receiver side and the payment on the
434+
// sender side show the individual HTLCs that arrived for it and that
435+
// they show the correct asset amounts when decoded.
436+
assertInvoiceHtlcAssets(
437+
t.t, charlie, invoiceResp, charlieInvoiceAmount,
438+
)
439+
assertPaymentHtlcAssets(
440+
t.t, dave, invoiceResp.RHash, charlieInvoiceAmount,
441+
)
442+
423443
charlieAssetBalance += charlieInvoiceAmount
424444
daveAssetBalance -= charlieInvoiceAmount
425445

@@ -914,6 +934,16 @@ func testCustomChannelsGroupedAsset(_ context.Context, net *NetworkHarness,
914934
payInvoiceWithAssets(t.t, charlie, dave, invoiceResp, assetID, true)
915935
logBalance(t.t, nodes, assetID, "after invoice")
916936

937+
// Make sure the invoice on the receiver side and the payment on the
938+
// sender side show the individual HTLCs that arrived for it and that
939+
// they show the correct asset amounts when decoded.
940+
assertInvoiceHtlcAssets(
941+
t.t, dave, invoiceResp, daveInvoiceAssetAmount,
942+
)
943+
assertPaymentHtlcAssets(
944+
t.t, charlie, invoiceResp.RHash, daveInvoiceAssetAmount,
945+
)
946+
917947
charlieAssetBalance -= daveInvoiceAssetAmount
918948
daveAssetBalance += daveInvoiceAssetAmount
919949

@@ -1906,27 +1936,38 @@ func testCustomChannelsLiquidityEdgeCases(_ context.Context,
19061936
"invoice, multi-hop)")
19071937

19081938
// Edge case: Big asset invoice paid by direct peer with assets.
1939+
const bigAssetAmount = 100_000
19091940
invoiceResp := createAssetInvoice(
1910-
t.t, charlie, dave, 100_000, assetID,
1941+
t.t, charlie, dave, bigAssetAmount, assetID,
19111942
)
1912-
19131943
payInvoiceWithAssets(t.t, charlie, dave, invoiceResp, assetID, false)
19141944

19151945
logBalance(t.t, nodes, assetID, "after big asset payment (asset "+
19161946
"invoice, direct)")
19171947

1948+
// Make sure the invoice on the receiver side and the payment on the
1949+
// sender side show the individual HTLCs that arrived for it and that
1950+
// they show the correct asset amounts when decoded.
1951+
assertInvoiceHtlcAssets(
1952+
t.t, dave, invoiceResp, bigAssetAmount,
1953+
)
1954+
assertPaymentHtlcAssets(
1955+
t.t, charlie, invoiceResp.RHash, bigAssetAmount,
1956+
)
1957+
19181958
// Edge case: Big normal invoice, paid by direct channel peer with
19191959
// assets.
1960+
const hugeAssetAmount = 1_000_000
19201961
_ = createAndPayNormalInvoice(
1921-
t.t, dave, charlie, charlie, 1_000_000, assetID, true,
1962+
t.t, dave, charlie, charlie, hugeAssetAmount, assetID, true,
19221963
)
19231964

19241965
logBalance(t.t, nodes, assetID, "after big asset payment (btc "+
19251966
"invoice, direct)")
19261967

19271968
// Dave sends 200k assets and 2k sats to Yara.
19281969
sendAssetKeySendPayment(
1929-
t.t, dave, yara, 200_000, assetID,
1970+
t.t, dave, yara, 2*bigAssetAmount, assetID,
19301971
fn.None[int64](), lnrpc.Payment_SUCCEEDED,
19311972
fn.None[lnrpc.PaymentFailureReason](),
19321973
)
@@ -1939,7 +1980,7 @@ func testCustomChannelsLiquidityEdgeCases(_ context.Context,
19391980
// channels, where the total asset value exceeds the btc capacity of the
19401981
// channels.
19411982
invoiceResp = createAssetInvoice(
1942-
t.t, dave, charlie, 100_000, assetID,
1983+
t.t, dave, charlie, bigAssetAmount, assetID,
19431984
)
19441985

19451986
payInvoiceWithAssets(t.t, yara, dave, invoiceResp, assetID, false)

0 commit comments

Comments
 (0)