diff --git a/itest/list_on_test.go b/itest/list_on_test.go index 7560fb16b..fe6c37385 100644 --- a/itest/list_on_test.go +++ b/itest/list_on_test.go @@ -710,4 +710,8 @@ var allTestCases = []*lntest.TestCase{ Name: "experimental endorsement", TestFunc: testExperimentalEndorsement, }, + { + Name: "quiescence", + TestFunc: testQuiescence, + }, } diff --git a/itest/lnd_quiescence_test.go b/itest/lnd_quiescence_test.go new file mode 100644 index 000000000..7c2c274a2 --- /dev/null +++ b/itest/lnd_quiescence_test.go @@ -0,0 +1,48 @@ +package itest + +import ( + "github.com/btcsuite/btcd/btcutil" + "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lnrpc/devrpc" + "github.com/lightningnetwork/lnd/lnrpc/routerrpc" + "github.com/lightningnetwork/lnd/lntest" + "github.com/stretchr/testify/require" +) + +// testQuiescence tests whether we can come to agreement on quiescence of a +// channel. We initiate quiescence via RPC and if it succeeds we verify that +// the expected initiator is the resulting initiator. +// +// NOTE FOR REVIEW: this could be improved by blasting the channel with HTLC +// traffic on both sides to increase the surface area of the change under test. +func testQuiescence(ht *lntest.HarnessTest) { + alice, bob := ht.Alice, ht.Bob + + chanPoint := ht.OpenChannel(bob, alice, lntest.OpenChannelParams{ + Amt: btcutil.Amount(1000000), + }) + defer ht.CloseChannel(bob, chanPoint) + + res := alice.RPC.Quiesce(&devrpc.QuiescenceRequest{ + ChanId: chanPoint, + }) + + require.True(ht, res.Initiator) + + req := &routerrpc.SendPaymentRequest{ + Dest: ht.Alice.PubKey[:], + Amt: 100, + PaymentHash: ht.Random32Bytes(), + FinalCltvDelta: finalCltvDelta, + TimeoutSeconds: 60, + FeeLimitMsat: noFeeLimitMsat, + } + + ht.SendPaymentAssertFail( + ht.Bob, req, + // This fails with insufficient balance because the bandwidth + // manager reports 0 bandwidth if a link is not eligible for + // forwarding, which is the case during quiescence. + lnrpc.PaymentFailureReason_FAILURE_REASON_INSUFFICIENT_BALANCE, + ) +} diff --git a/lntest/rpc/lnd.go b/lntest/rpc/lnd.go index f0ed52fd8..1657caac8 100644 --- a/lntest/rpc/lnd.go +++ b/lntest/rpc/lnd.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lnrpc/devrpc" "github.com/stretchr/testify/require" ) @@ -730,3 +731,17 @@ func (h *HarnessRPC) LookupHtlcResolutionAssertErr( return err } + +// Quiesce makes an RPC call to the node's Quiesce method and returns the +// response. +func (h *HarnessRPC) Quiesce( + req *devrpc.QuiescenceRequest) *devrpc.QuiescenceResponse { + + ctx, cancel := context.WithTimeout(h.runCtx, DefaultTimeout) + defer cancel() + + res, err := h.Dev.Quiesce(ctx, req) + h.NoError(err, "Quiesce returned an error") + + return res +}