Skip to content

Commit 27d4e91

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 af9c9bd commit 27d4e91

File tree

2 files changed

+142
-5
lines changed

2 files changed

+142
-5
lines changed

itest/assets_test.go

Lines changed: 96 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,101 @@ 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 for the given ID when decoded.
845+
func assertInvoiceHtlcAssets(t *testing.T, node *HarnessNode,
846+
addedInvoice *lnrpc.AddInvoiceResponse, assetID []byte,
847+
assetAmount uint64) {
848+
849+
ctxb := context.Background()
850+
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
851+
defer cancel()
852+
853+
invoice, err := node.InvoicesClient.LookupInvoiceV2(
854+
ctxt, &invoicesrpc.LookupInvoiceMsg{
855+
InvoiceRef: &invoicesrpc.LookupInvoiceMsg_PaymentAddr{
856+
PaymentAddr: addedInvoice.PaymentAddr,
857+
},
858+
},
859+
)
860+
require.NoError(t, err)
861+
require.NotEmpty(t, invoice.Htlcs)
862+
863+
t.Logf("Asset invoice: %v", toProtoJSON(t, invoice))
864+
865+
targetID := hex.EncodeToString(assetID)
866+
867+
var totalAssetAmount uint64
868+
for _, htlc := range invoice.Htlcs {
869+
require.NotEmpty(t, htlc.CustomChannelData)
870+
871+
jsonHtlc := &rfqmsg.JsonHtlc{}
872+
err := json.Unmarshal(htlc.CustomChannelData, jsonHtlc)
873+
require.NoError(t, err)
874+
875+
for _, balance := range jsonHtlc.Balances {
876+
if balance.AssetID != targetID {
877+
continue
878+
}
879+
880+
totalAssetAmount += balance.Amount
881+
}
882+
}
883+
884+
// Due to rounding we allow up to 1 unit of error.
885+
require.InDelta(t, assetAmount, totalAssetAmount, 1)
886+
}
887+
888+
// assertPaymentHtlcAssets makes sure the payment with the given hash shows the
889+
// individual HTLCs that arrived for it and that they show the correct asset
890+
// amounts for the given ID when decoded.
891+
func assertPaymentHtlcAssets(t *testing.T, node *HarnessNode, payHash []byte,
892+
assetID []byte, assetAmount uint64) {
893+
894+
ctxb := context.Background()
895+
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
896+
defer cancel()
897+
898+
stream, err := node.RouterClient.TrackPaymentV2(
899+
ctxt, &routerrpc.TrackPaymentRequest{
900+
PaymentHash: payHash,
901+
NoInflightUpdates: true,
902+
},
903+
)
904+
require.NoError(t, err)
905+
906+
payment, err := stream.Recv()
907+
require.NoError(t, err)
908+
require.NotNil(t, payment)
909+
require.NotEmpty(t, payment.Htlcs)
910+
911+
t.Logf("Asset payment: %v", toProtoJSON(t, payment))
912+
913+
targetID := hex.EncodeToString(assetID)
914+
915+
var totalAssetAmount uint64
916+
for _, htlc := range payment.Htlcs {
917+
require.NotNil(t, htlc.Route)
918+
require.NotEmpty(t, htlc.Route.CustomChannelData)
919+
920+
jsonHtlc := &rfqmsg.JsonHtlc{}
921+
err := json.Unmarshal(htlc.Route.CustomChannelData, jsonHtlc)
922+
require.NoError(t, err)
923+
924+
for _, balance := range jsonHtlc.Balances {
925+
if balance.AssetID != targetID {
926+
continue
927+
}
928+
929+
totalAssetAmount += balance.Amount
930+
}
931+
}
932+
933+
// Due to rounding we allow up to 1 unit of error.
934+
require.InDelta(t, assetAmount, totalAssetAmount, 1)
935+
}
936+
841937
func waitForSendEvent(t *testing.T,
842938
sendEvents taprpc.TaprootAssets_SubscribeSendEventsClient,
843939
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, assetID, largeInvoiceAmount,
242+
)
243+
assertPaymentHtlcAssets(
244+
t.t, charlie, invoiceResp3.RHash, assetID, 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, assetID, charlieInvoiceAmount,
438+
)
439+
assertPaymentHtlcAssets(
440+
t.t, dave, invoiceResp.RHash, assetID, 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, assetID, daveInvoiceAssetAmount,
942+
)
943+
assertPaymentHtlcAssets(
944+
t.t, charlie, invoiceResp.RHash, assetID, 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, assetID, bigAssetAmount,
1953+
)
1954+
assertPaymentHtlcAssets(
1955+
t.t, charlie, invoiceResp.RHash, assetID, 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)