mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-09-06 01:18:17 +02:00
multi: move itest
out of lntest
This commit moves all the test cases living in `itest` out of `lntest`, further making `lntest` an independent package for general testing.
This commit is contained in:
158
itest/lnd_max_htlcs_test.go
Normal file
158
itest/lnd_max_htlcs_test.go
Normal file
@@ -0,0 +1,158 @@
|
||||
package itest
|
||||
|
||||
import (
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// testMaxHtlcPathfind tests the case where we try to send a payment over a
|
||||
// channel where we have already reached the limit of the number of htlcs that
|
||||
// we may add to the remote party's commitment. This test asserts that we do
|
||||
// not attempt to use the full channel at all in our pathfinding.
|
||||
func testMaxHtlcPathfind(ht *lntemp.HarnessTest) {
|
||||
// Setup a channel between Alice and Bob where Alice will only allow
|
||||
// Bob to add a maximum of 5 htlcs to her commitment.
|
||||
maxHtlcs := 5
|
||||
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
chanPoint := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{
|
||||
Amt: 1000000,
|
||||
PushAmt: 800000,
|
||||
RemoteMaxHtlcs: uint16(maxHtlcs),
|
||||
},
|
||||
)
|
||||
|
||||
// Alice and bob should have one channel open with each other now.
|
||||
ht.AssertNodeNumChannels(alice, 1)
|
||||
ht.AssertNodeNumChannels(bob, 1)
|
||||
|
||||
// Send our maximum number of htlcs from Bob -> Alice so that we get
|
||||
// to a point where Alice won't accept any more htlcs on the channel.
|
||||
subscriptions := make([]*holdSubscription, maxHtlcs)
|
||||
|
||||
for i := 0; i < maxHtlcs; i++ {
|
||||
subscriptions[i] = acceptHoldInvoice(ht, i, bob, alice)
|
||||
}
|
||||
|
||||
ht.AssertNumActiveHtlcs(alice, maxHtlcs)
|
||||
ht.AssertNumActiveHtlcs(bob, maxHtlcs)
|
||||
|
||||
// Now we send a payment from Alice -> Bob to sanity check that our
|
||||
// commitment limit is not applied in the opposite direction.
|
||||
aliceBobSub := acceptHoldInvoice(ht, maxHtlcs, alice, bob)
|
||||
ht.AssertNumActiveHtlcs(alice, maxHtlcs+1)
|
||||
ht.AssertNumActiveHtlcs(bob, maxHtlcs+1)
|
||||
|
||||
// Now, we're going to try to send another payment from Bob -> Alice.
|
||||
// We've hit our max remote htlcs, so we expect this payment to spin
|
||||
// out dramatically with pathfinding.
|
||||
sendReq := &routerrpc.SendPaymentRequest{
|
||||
Amt: 1000,
|
||||
Dest: alice.PubKey[:],
|
||||
TimeoutSeconds: 60,
|
||||
FeeLimitSat: 1000000,
|
||||
MaxParts: 10,
|
||||
Amp: true,
|
||||
}
|
||||
ht.SendPaymentAndAssertStatus(bob, sendReq, lnrpc.Payment_FAILED)
|
||||
|
||||
// Now that we're done, we cancel all our pending htlcs so that we
|
||||
// can cleanup the channel with a coop close.
|
||||
for _, sub := range subscriptions {
|
||||
sub.cancel(ht)
|
||||
}
|
||||
aliceBobSub.cancel(ht)
|
||||
|
||||
ht.AssertNumActiveHtlcs(alice, 0)
|
||||
ht.AssertNumActiveHtlcs(bob, 0)
|
||||
|
||||
ht.CloseChannel(alice, chanPoint)
|
||||
}
|
||||
|
||||
type holdSubscription struct {
|
||||
recipient *node.HarnessNode
|
||||
hash lntypes.Hash
|
||||
invSubscription invoicesrpc.Invoices_SubscribeSingleInvoiceClient
|
||||
paymentSubscription routerrpc.Router_SendPaymentV2Client
|
||||
}
|
||||
|
||||
// cancel updates a hold invoice to cancel from the recipient and consumes
|
||||
// updates from the payer until it has reached a final, failed state.
|
||||
func (h *holdSubscription) cancel(ht *lntemp.HarnessTest) {
|
||||
h.recipient.RPC.CancelInvoice(h.hash[:])
|
||||
|
||||
invUpdate := ht.ReceiveSingleInvoice(h.invSubscription)
|
||||
require.Equal(ht, lnrpc.Invoice_CANCELED, invUpdate.State,
|
||||
"expected invoice canceled")
|
||||
|
||||
// We expect one in flight update when our htlc is canceled back, and
|
||||
// another when we fail the payment as a whole.
|
||||
payUpdate := ht.AssertPaymentStatusFromStream(
|
||||
h.paymentSubscription, lnrpc.Payment_IN_FLIGHT,
|
||||
)
|
||||
require.Len(ht, payUpdate.Htlcs, 1)
|
||||
|
||||
payUpdate = ht.AssertPaymentStatusFromStream(
|
||||
h.paymentSubscription, lnrpc.Payment_FAILED,
|
||||
)
|
||||
require.Equal(ht, lnrpc.Payment_FAILED, payUpdate.Status,
|
||||
"expected payment failed")
|
||||
require.Equal(ht, lnrpc.PaymentFailureReason_FAILURE_REASON_INCORRECT_PAYMENT_DETAILS, //nolint:lll
|
||||
payUpdate.FailureReason, "expected unknown details")
|
||||
}
|
||||
|
||||
// acceptHoldInvoice adds a hold invoice to the recipient node, pays it from
|
||||
// the sender and asserts that we have reached the accepted state where htlcs
|
||||
// are locked in for the payment.
|
||||
func acceptHoldInvoice(ht *lntemp.HarnessTest, idx int, sender,
|
||||
receiver *node.HarnessNode) *holdSubscription {
|
||||
|
||||
hash := [lntypes.HashSize]byte{byte(idx + 1)}
|
||||
|
||||
req := &invoicesrpc.AddHoldInvoiceRequest{
|
||||
ValueMsat: 10000,
|
||||
Hash: hash[:],
|
||||
}
|
||||
invoice := receiver.RPC.AddHoldInvoice(req)
|
||||
|
||||
invStream := receiver.RPC.SubscribeSingleInvoice(hash[:])
|
||||
inv := ht.ReceiveSingleInvoice(invStream)
|
||||
require.Equal(ht, lnrpc.Invoice_OPEN, inv.State, "expect open")
|
||||
|
||||
sendReq := &routerrpc.SendPaymentRequest{
|
||||
PaymentRequest: invoice.PaymentRequest,
|
||||
TimeoutSeconds: 60,
|
||||
FeeLimitSat: 1000000,
|
||||
}
|
||||
payStream := sender.RPC.SendPayment(sendReq)
|
||||
|
||||
// Finally, assert that we progress to an accepted state. We expect
|
||||
// the payer to get one update for the creation of the payment, and
|
||||
// another when a htlc is dispatched.
|
||||
payment := ht.AssertPaymentStatusFromStream(
|
||||
payStream, lnrpc.Payment_IN_FLIGHT,
|
||||
)
|
||||
require.Empty(ht, payment.Htlcs)
|
||||
|
||||
payment = ht.AssertPaymentStatusFromStream(
|
||||
payStream, lnrpc.Payment_IN_FLIGHT,
|
||||
)
|
||||
require.Len(ht, payment.Htlcs, 1)
|
||||
|
||||
inv = ht.ReceiveSingleInvoice(invStream)
|
||||
require.Equal(ht, lnrpc.Invoice_ACCEPTED, inv.State,
|
||||
"expected accepted")
|
||||
|
||||
return &holdSubscription{
|
||||
recipient: receiver,
|
||||
hash: hash,
|
||||
invSubscription: invStream,
|
||||
paymentSubscription: payStream,
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user