itest: add assets to btc self-payment test case

This commit is contained in:
Oliver Gugger 2025-06-04 11:03:16 +02:00
parent d3e9d2782c
commit 33f4ef3872
No known key found for this signature in database
GPG key ID: 8E4256593F177720
2 changed files with 112 additions and 14 deletions

View file

@ -1282,6 +1282,20 @@ func assertChannelAssetBalanceWithDelta(t *testing.T, node *HarnessNode,
require.InDelta(t, remote, assetBalance.RemoteBalance, delta)
}
func channelAssetBalance(t *testing.T, node *HarnessNode,
chanPoint *lnrpc.ChannelPoint) (uint64, uint64) {
targetChan := fetchChannel(t, node, chanPoint)
var assetBalance rfqmsg.JsonAssetChannel
err := json.Unmarshal(targetChan.CustomChannelData, &assetBalance)
require.NoError(t, err)
require.GreaterOrEqual(t, len(assetBalance.FundingAssets), 1)
return assetBalance.LocalBalance, assetBalance.RemoteBalance
}
// addRoutingFee adds the default routing fee (1 part per million fee rate plus
// 1000 milli-satoshi base fee) to the given milli-satoshi amount.
func addRoutingFee(amt lnwire.MilliSatoshi) lnwire.MilliSatoshi {
@ -1321,6 +1335,8 @@ func sendAssetKeySendPayment(t *testing.T, src, dst *HarnessNode, amt uint64,
PaymentHash: hash[:],
TimeoutSeconds: int32(PaymentTimeout.Seconds()),
MaxParts: cfg.maxShards,
OutgoingChanIds: cfg.outgoingChanIDs,
AllowSelfPayment: cfg.allowSelfPayment,
}
request := &tchrpc.SendPaymentRequest{
@ -1402,7 +1418,13 @@ func createAndPayNormalInvoiceWithBtc(t *testing.T, src, dst *HarnessNode,
}
func createNormalInvoice(t *testing.T, dst *HarnessNode,
amountSat btcutil.Amount) *lnrpc.AddInvoiceResponse {
amountSat btcutil.Amount,
opts ...invoiceOpt) *lnrpc.AddInvoiceResponse {
cfg := defaultInvoiceConfig()
for _, opt := range opts {
opt(cfg)
}
ctxb := context.Background()
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
@ -1410,9 +1432,10 @@ func createNormalInvoice(t *testing.T, dst *HarnessNode,
expirySeconds := 10
invoiceResp, err := dst.AddInvoice(ctxt, &lnrpc.Invoice{
Value: int64(amountSat),
Memo: "normal invoice",
Expiry: int64(expirySeconds),
Value: int64(amountSat),
Memo: "normal invoice",
Expiry: int64(expirySeconds),
RouteHints: cfg.routeHints,
})
require.NoError(t, err)
@ -1448,12 +1471,6 @@ func payPayReqWithSatoshi(t *testing.T, payer *HarnessNode, payReq string,
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
defer cancel()
shardSize := uint64(0)
if cfg.smallShards {
shardSize = 80_000_000
}
sendReq := &routerrpc.SendPaymentRequest{
PaymentRequest: payReq,
TimeoutSeconds: int32(PaymentTimeout.Seconds()),
@ -1461,7 +1478,6 @@ func payPayReqWithSatoshi(t *testing.T, payer *HarnessNode, payReq string,
MaxParts: cfg.maxShards,
OutgoingChanIds: cfg.outgoingChanIDs,
AllowSelfPayment: cfg.allowSelfPayment,
MaxShardSizeMsat: shardSize,
}
if cfg.smallShards {
@ -1652,6 +1668,8 @@ func payInvoiceWithAssets(t *testing.T, payer, rfqPeer *HarnessNode,
FeeLimitMsat: int64(cfg.feeLimit),
DestCustomRecords: cfg.destCustomRecords,
MaxParts: cfg.maxShards,
OutgoingChanIds: cfg.outgoingChanIDs,
AllowSelfPayment: cfg.allowSelfPayment,
}
if cfg.smallShards {
@ -1768,6 +1786,12 @@ func withMsatAmount(amt uint64) invoiceOpt {
}
}
func withRouteHints(hints []*lnrpc.RouteHint) invoiceOpt {
return func(c *invoiceConfig) {
c.routeHints = hints
}
}
func createAssetInvoice(t *testing.T, dstRfqPeer, dst *HarnessNode,
assetAmount uint64, assetID []byte,
opts ...invoiceOpt) *lnrpc.AddInvoiceResponse {
@ -1795,14 +1819,14 @@ func createAssetInvoice(t *testing.T, dstRfqPeer, dst *HarnessNode,
dstTapd := newTapClient(t, dst)
request := &tchrpc.AddInvoiceRequest{
GroupKey: cfg.groupKey,
AssetAmount: assetAmount,
PeerPubkey: peerPubKey,
InvoiceRequest: &lnrpc.Invoice{
Memo: fmt.Sprintf("this is an asset invoice for "+
"%d units", assetAmount),
Expiry: timeoutSeconds,
ValueMsat: int64(cfg.msats),
Expiry: timeoutSeconds,
ValueMsat: int64(cfg.msats),
RouteHints: cfg.routeHints,
},
}

View file

@ -4611,6 +4611,8 @@ func testCustomChannelsSelfPayment(ctx context.Context, net *NetworkHarness,
)
defer closeChannelAndAssert(t, net, alice, satChanPoint, false)
assetChan := fetchChannel(t.t, alice, assetChanPoint)
assetChanSCID := assetChan.ChanId
satChan := fetchChannel(t.t, alice, satChanPoint)
satChanSCID := satChan.ChanId
@ -4624,6 +4626,7 @@ func testCustomChannelsSelfPayment(ctx context.Context, net *NetworkHarness,
assetKeySendAmount = 15_000
numInvoicePayments = 10
assetInvoiceAmount = 1_234
btcInvoiceAmount = 10_000
btcKeySendAmount = 200_000
btcReserveAmount = 2000
btcHtlcCost = numInvoicePayments * 354
@ -4695,4 +4698,75 @@ func testCustomChannelsSelfPayment(ctx context.Context, net *NetworkHarness,
decodedInvoice.NumSatoshis,
)
}
// We now do the opposite: We create a satoshi invoice on Alice and
// attempt to pay it with assets.
aliceAssetBalance, bobAssetBalance = channelAssetBalance(
t.t, alice, assetChanPoint,
)
for i := 0; i < numInvoicePayments; i++ {
// The BTC balance of Alice before we start the payment. We
// expect that to go down by at least the invoice amount.
btcBalanceAliceBefore := fetchChannel(
t.t, alice, satChanPoint,
).LocalBalance
hopHint := &lnrpc.HopHint{
NodeId: bob.PubKeyStr,
ChanId: satChan.PeerScidAlias,
CltvExpiryDelta: 80,
FeeBaseMsat: 1000,
FeeProportionalMillionths: 1,
}
invoiceResp := createNormalInvoice(
t.t, alice, btcInvoiceAmount, withRouteHints(
[]*lnrpc.RouteHint{{
HopHints: []*lnrpc.HopHint{hopHint},
}},
),
)
sentUnits, _ := payInvoiceWithAssets(
t.t, alice, bob, invoiceResp.PaymentRequest, assetID,
withAllowSelfPayment(), withOutgoingChanIDs(
[]uint64{assetChanSCID},
),
)
logBalance(
t.t, nodes, assetID,
"after paying sat invoice "+strconv.Itoa(i),
)
// The accumulated delta from the rounding of multiple sends.
// We basically allow the balance to be off by one unit for each
// payment.
delta := float64(i + 1)
// We now expect the channel balance to have increased in the
// BTC channel and decreased in the assets channel.
assertChannelAssetBalanceWithDelta(
t.t, alice, assetChanPoint,
aliceAssetBalance-sentUnits,
bobAssetBalance+sentUnits, delta,
)
aliceAssetBalance -= sentUnits
bobAssetBalance += sentUnits
btcBalanceAliceAfter := fetchChannel(
t.t, alice, satChanPoint,
).LocalBalance
// The difference between the two balances should be at least
// the invoice amount.
decodedInvoice, err := alice.DecodePayReq(
context.Background(), &lnrpc.PayReqString{
PayReq: invoiceResp.PaymentRequest,
},
)
require.NoError(t.t, err)
require.GreaterOrEqual(
t.t, btcBalanceAliceAfter-btcBalanceAliceBefore,
decodedInvoice.NumSatoshis,
)
}
}