diff --git a/itest/list_on_test.go b/itest/list_on_test.go index 9a1d8ebe3..39b9ed22e 100644 --- a/itest/list_on_test.go +++ b/itest/list_on_test.go @@ -715,6 +715,10 @@ var allTestCases = []*lntest.TestCase{ Name: "peer bootstrapping", TestFunc: testPeerBootstrapping, }, + { + Name: "grpc not found", + TestFunc: testGRPCNotFound, + }, } // appendPrefixed is used to add a prefix to each test name in the subtests diff --git a/itest/lnd_misc_test.go b/itest/lnd_misc_test.go index 4756ca742..66b7fadf4 100644 --- a/itest/lnd_misc_test.go +++ b/itest/lnd_misc_test.go @@ -1,6 +1,7 @@ package itest import ( + "crypto/rand" "encoding/hex" "fmt" "os" @@ -21,7 +22,9 @@ import ( "github.com/lightningnetwork/lnd/lntest/wait" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/routing/route" "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" ) // testSphinxReplayPersistence verifies that replayed onion packets are @@ -1344,3 +1347,51 @@ func testSendSelectedCoinsChannelReserve(ht *lntest.HarnessTest) { // Alice should have one reserved UTXO now. ht.AssertNumUTXOs(alice, 1) } + +// testGRPCNotFound verifies that the expected grpc NotFound status code is +// returned when querying various rpc endpoints. +func testGRPCNotFound(ht *lntest.HarnessTest) { + var ( + notFoundErr = codes.NotFound.String() + unknownPub = "0286098b97bc843372b4426d4b276cea9aa2f48f0428d6" + + "f5b66ae101befc14f8b4" + rHash = make([]byte, 32) + ) + unknownPubBytes, err := route.NewVertexFromStr(unknownPub) + require.NoError(ht, err) + + _, err = rand.Read(rHash) + require.NoError(ht, err) + + alice := ht.NewNode("Alice", []string{ + // We add this flag so that we can test the + // LookupHTLCResolutionAssertErr endpoint. + "--store-final-htlc-resolutions", + }).RPC + + alice.GetChanInfoAssertErr(&lnrpc.ChanInfoRequest{ + // Use a random channel ID that doesn't exist. + ChanId: 949807622323240961, + }, notFoundErr) + + alice.GetNodeInfoAssertErr(&lnrpc.NodeInfoRequest{ + // Use a random pubkey that doesn't exist. + PubKey: unknownPub, + }, notFoundErr) + + alice.SendCustomMessageAssertErr(&lnrpc.SendCustomMessageRequest{ + // Use a random pubkey that doesn't exist. + Peer: unknownPubBytes[:], + Data: []byte("test message"), + }, notFoundErr) + + alice.LookupHTLCResolutionAssertErr(&lnrpc.LookupHtlcResolutionRequest{ + ChanId: 400000, + HtlcIndex: 300, + }, notFoundErr) + + alice.LookupInvoiceAssertErr(&lnrpc.PaymentHash{ + // Use a random payment hash that doesn't exist. + RHash: rHash, + }, notFoundErr) +} diff --git a/lntest/rpc/lnd.go b/lntest/rpc/lnd.go index 055b3f29b..e8f359be6 100644 --- a/lntest/rpc/lnd.go +++ b/lntest/rpc/lnd.go @@ -303,6 +303,66 @@ func (h *HarnessRPC) AddInvoiceAssertErr(req *lnrpc.Invoice, errStr string) { require.ErrorContains(h, err, errStr) } +// GetChanInfoAssertErr makes an RPC call to GetChanInfo and asserts an error +// has returned with a specific error message. +func (h *HarnessRPC) GetChanInfoAssertErr(req *lnrpc.ChanInfoRequest, + errStr string) { + + ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout) + defer cancel() + + _, err := h.LN.GetChanInfo(ctxt, req) + require.ErrorContains(h, err, errStr) +} + +// GetNodeInfoAssertErr makes an RPC call to GetNodeInfo and asserts an error +// has returned with a specific error message. +func (h *HarnessRPC) GetNodeInfoAssertErr(req *lnrpc.NodeInfoRequest, + errStr string) { + + ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout) + defer cancel() + + _, err := h.LN.GetNodeInfo(ctxt, req) + require.ErrorContains(h, err, errStr) +} + +// SendCustomMessageAssertErr makes an RPC call to SendCustomMessage and asserts +// an error has returned with a specific error message. +func (h *HarnessRPC) SendCustomMessageAssertErr( + req *lnrpc.SendCustomMessageRequest, errStr string) { + + ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout) + defer cancel() + + _, err := h.LN.SendCustomMessage(ctxt, req) + require.ErrorContains(h, err, errStr) +} + +// LookupInvoiceAssertErr makes an RPC call to LookupInvoice and asserts an +// error has returned with a specific error message. +func (h *HarnessRPC) LookupInvoiceAssertErr(req *lnrpc.PaymentHash, + errStr string) { + + ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout) + defer cancel() + + _, err := h.LN.LookupInvoice(ctxt, req) + require.ErrorContains(h, err, errStr) +} + +// LookupHTLCResolutionAssertErr makes an RPC call to LookupHTLCResolution and +// asserts an error has returned with a specific error message. +func (h *HarnessRPC) LookupHTLCResolutionAssertErr( + req *lnrpc.LookupHtlcResolutionRequest, errStr string) { + + ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout) + defer cancel() + + _, err := h.LN.LookupHtlcResolution(ctxt, req) + require.ErrorContains(h, err, errStr) +} + // AbandonChannel makes a RPC call to AbandonChannel and asserts. func (h *HarnessRPC) AbandonChannel( req *lnrpc.AbandonChannelRequest) *lnrpc.AbandonChannelResponse {