From 8299d632e8fa15489c439145490c04553a8426b8 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 28 Sep 2021 19:52:46 -0700 Subject: [PATCH] lnrpc/invoicesrpc: add new invoice ref LookupInvoiceV2 method In this commit, we add a new `LookupInvoiceV2` method attached to the invoice RPC sub-server. Compared to the existing version, this version allows an invoice to be looked up by an invoice ref. This enables users to query an AMP invoice based on a specific _set ID_, so they can get the information related to the set of cumulative settles to that invoices. --- invoices/invoiceregistry.go | 8 + lnrpc/invoicesrpc/invoices.pb.go | 197 +++++++++++++++++++----- lnrpc/invoicesrpc/invoices.pb.gw.go | 83 ++++++++++ lnrpc/invoicesrpc/invoices.pb.json.go | 25 +++ lnrpc/invoicesrpc/invoices.proto | 14 ++ lnrpc/invoicesrpc/invoices.swagger.json | 46 ++++++ lnrpc/invoicesrpc/invoices.yaml | 2 + lnrpc/invoicesrpc/invoices_grpc.pb.go | 42 +++++ lnrpc/invoicesrpc/invoices_server.go | 59 +++++++ 9 files changed, 441 insertions(+), 35 deletions(-) diff --git a/invoices/invoiceregistry.go b/invoices/invoiceregistry.go index 1e705c651..f774d353e 100644 --- a/invoices/invoiceregistry.go +++ b/invoices/invoiceregistry.go @@ -606,6 +606,14 @@ func (i *InvoiceRegistry) LookupInvoice(rHash lntypes.Hash) (channeldb.Invoice, return i.cdb.LookupInvoice(ref) } +// LookupInvoiceByRef looks up an invoice by the given reference, if found +// then we're able to pull the funds pending within an HTLC. +func (i *InvoiceRegistry) LookupInvoiceByRef( + ref channeldb.InvoiceRef) (channeldb.Invoice, error) { + + return i.cdb.LookupInvoice(ref) +} + // startHtlcTimer starts a new timer via the invoice registry main loop that // cancels a single htlc on an invoice when the htlc hold duration has passed. func (i *InvoiceRegistry) startHtlcTimer(invoiceRef channeldb.InvoiceRef, diff --git a/lnrpc/invoicesrpc/invoices.pb.go b/lnrpc/invoicesrpc/invoices.pb.go index a2e804a98..99a2f9657 100644 --- a/lnrpc/invoicesrpc/invoices.pb.go +++ b/lnrpc/invoicesrpc/invoices.pb.go @@ -462,6 +462,100 @@ func (x *SubscribeSingleInvoiceRequest) GetRHash() []byte { return nil } +type LookupInvoiceMsg struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to InvoiceRef: + // *LookupInvoiceMsg_PaymentHash + // *LookupInvoiceMsg_PaymentAddr + // *LookupInvoiceMsg_SetId + InvoiceRef isLookupInvoiceMsg_InvoiceRef `protobuf_oneof:"invoice_ref"` +} + +func (x *LookupInvoiceMsg) Reset() { + *x = LookupInvoiceMsg{} + if protoimpl.UnsafeEnabled { + mi := &file_invoicesrpc_invoices_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LookupInvoiceMsg) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LookupInvoiceMsg) ProtoMessage() {} + +func (x *LookupInvoiceMsg) ProtoReflect() protoreflect.Message { + mi := &file_invoicesrpc_invoices_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LookupInvoiceMsg.ProtoReflect.Descriptor instead. +func (*LookupInvoiceMsg) Descriptor() ([]byte, []int) { + return file_invoicesrpc_invoices_proto_rawDescGZIP(), []int{7} +} + +func (m *LookupInvoiceMsg) GetInvoiceRef() isLookupInvoiceMsg_InvoiceRef { + if m != nil { + return m.InvoiceRef + } + return nil +} + +func (x *LookupInvoiceMsg) GetPaymentHash() []byte { + if x, ok := x.GetInvoiceRef().(*LookupInvoiceMsg_PaymentHash); ok { + return x.PaymentHash + } + return nil +} + +func (x *LookupInvoiceMsg) GetPaymentAddr() []byte { + if x, ok := x.GetInvoiceRef().(*LookupInvoiceMsg_PaymentAddr); ok { + return x.PaymentAddr + } + return nil +} + +func (x *LookupInvoiceMsg) GetSetId() []byte { + if x, ok := x.GetInvoiceRef().(*LookupInvoiceMsg_SetId); ok { + return x.SetId + } + return nil +} + +type isLookupInvoiceMsg_InvoiceRef interface { + isLookupInvoiceMsg_InvoiceRef() +} + +type LookupInvoiceMsg_PaymentHash struct { + PaymentHash []byte `protobuf:"bytes,1,opt,name=payment_hash,json=paymentHash,proto3,oneof"` +} + +type LookupInvoiceMsg_PaymentAddr struct { + PaymentAddr []byte `protobuf:"bytes,2,opt,name=payment_addr,json=paymentAddr,proto3,oneof"` +} + +type LookupInvoiceMsg_SetId struct { + SetId []byte `protobuf:"bytes,3,opt,name=set_id,json=setId,proto3,oneof"` +} + +func (*LookupInvoiceMsg_PaymentHash) isLookupInvoiceMsg_InvoiceRef() {} + +func (*LookupInvoiceMsg_PaymentAddr) isLookupInvoiceMsg_InvoiceRef() {} + +func (*LookupInvoiceMsg_SetId) isLookupInvoiceMsg_InvoiceRef() {} + var File_invoicesrpc_invoices_proto protoreflect.FileDescriptor var file_invoicesrpc_invoices_proto_rawDesc = []byte{ @@ -510,32 +604,45 @@ var file_invoicesrpc_invoices_proto_rawDesc = []byte{ 0x72, 0x69, 0x62, 0x65, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x72, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x72, 0x48, 0x61, 0x73, 0x68, 0x4a, - 0x04, 0x08, 0x01, 0x10, 0x02, 0x32, 0xd9, 0x02, 0x0a, 0x08, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, - 0x65, 0x73, 0x12, 0x56, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x53, - 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x2a, 0x2e, 0x69, - 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x62, 0x65, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x30, 0x01, 0x12, 0x4e, 0x0a, 0x0d, 0x43, 0x61, - 0x6e, 0x63, 0x65, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x1d, 0x2e, 0x69, 0x6e, - 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, - 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x4d, 0x73, 0x67, 0x1a, 0x1e, 0x2e, 0x69, 0x6e, 0x76, - 0x6f, 0x69, 0x63, 0x65, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x49, - 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, 0x55, 0x0a, 0x0e, 0x41, 0x64, - 0x64, 0x48, 0x6f, 0x6c, 0x64, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x22, 0x2e, 0x69, - 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x48, 0x6f, - 0x6c, 0x64, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1f, 0x2e, 0x69, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x41, - 0x64, 0x64, 0x48, 0x6f, 0x6c, 0x64, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x12, 0x4e, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, + 0x04, 0x08, 0x01, 0x10, 0x02, 0x22, 0x84, 0x01, 0x0a, 0x10, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, + 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x4d, 0x73, 0x67, 0x12, 0x23, 0x0a, 0x0c, 0x70, 0x61, + 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x48, 0x00, 0x52, 0x0b, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, + 0x23, 0x0a, 0x0c, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0b, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, + 0x41, 0x64, 0x64, 0x72, 0x12, 0x17, 0x0a, 0x06, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x05, 0x73, 0x65, 0x74, 0x49, 0x64, 0x42, 0x0d, 0x0a, + 0x0b, 0x69, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x66, 0x32, 0x9b, 0x03, 0x0a, + 0x08, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x12, 0x56, 0x0a, 0x16, 0x53, 0x75, 0x62, + 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x6f, + 0x69, 0x63, 0x65, 0x12, 0x2a, 0x2e, 0x69, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x72, 0x70, + 0x63, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x53, 0x69, 0x6e, 0x67, 0x6c, + 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x0e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x30, + 0x01, 0x12, 0x4e, 0x0a, 0x0d, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x1d, 0x2e, 0x69, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x72, 0x70, 0x63, - 0x2e, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x4d, 0x73, + 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x4d, 0x73, 0x67, 0x1a, 0x1e, 0x2e, 0x69, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x72, 0x70, 0x63, 0x2e, - 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x2f, 0x6c, 0x6e, 0x64, 0x2f, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2f, 0x69, 0x6e, 0x76, 0x6f, 0x69, - 0x63, 0x65, 0x73, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x12, 0x55, 0x0a, 0x0e, 0x41, 0x64, 0x64, 0x48, 0x6f, 0x6c, 0x64, 0x49, 0x6e, 0x76, 0x6f, + 0x69, 0x63, 0x65, 0x12, 0x22, 0x2e, 0x69, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x72, 0x70, + 0x63, 0x2e, 0x41, 0x64, 0x64, 0x48, 0x6f, 0x6c, 0x64, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x69, 0x6e, 0x76, 0x6f, 0x69, 0x63, + 0x65, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x48, 0x6f, 0x6c, 0x64, 0x49, 0x6e, 0x76, + 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, 0x4e, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x74, + 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x1d, 0x2e, 0x69, 0x6e, 0x76, 0x6f, + 0x69, 0x63, 0x65, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x49, 0x6e, + 0x76, 0x6f, 0x69, 0x63, 0x65, 0x4d, 0x73, 0x67, 0x1a, 0x1e, 0x2e, 0x69, 0x6e, 0x76, 0x6f, 0x69, + 0x63, 0x65, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x49, 0x6e, 0x76, + 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, 0x40, 0x0a, 0x0f, 0x4c, 0x6f, 0x6f, 0x6b, + 0x75, 0x70, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x56, 0x32, 0x12, 0x1d, 0x2e, 0x69, 0x6e, + 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, + 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x4d, 0x73, 0x67, 0x1a, 0x0e, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, + 0x6e, 0x67, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x6c, 0x6e, 0x64, 0x2f, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2f, 0x69, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x72, 0x70, 0x63, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -550,7 +657,7 @@ func file_invoicesrpc_invoices_proto_rawDescGZIP() []byte { return file_invoicesrpc_invoices_proto_rawDescData } -var file_invoicesrpc_invoices_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_invoicesrpc_invoices_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_invoicesrpc_invoices_proto_goTypes = []interface{}{ (*CancelInvoiceMsg)(nil), // 0: invoicesrpc.CancelInvoiceMsg (*CancelInvoiceResp)(nil), // 1: invoicesrpc.CancelInvoiceResp @@ -559,21 +666,24 @@ var file_invoicesrpc_invoices_proto_goTypes = []interface{}{ (*SettleInvoiceMsg)(nil), // 4: invoicesrpc.SettleInvoiceMsg (*SettleInvoiceResp)(nil), // 5: invoicesrpc.SettleInvoiceResp (*SubscribeSingleInvoiceRequest)(nil), // 6: invoicesrpc.SubscribeSingleInvoiceRequest - (*lnrpc.RouteHint)(nil), // 7: lnrpc.RouteHint - (*lnrpc.Invoice)(nil), // 8: lnrpc.Invoice + (*LookupInvoiceMsg)(nil), // 7: invoicesrpc.LookupInvoiceMsg + (*lnrpc.RouteHint)(nil), // 8: lnrpc.RouteHint + (*lnrpc.Invoice)(nil), // 9: lnrpc.Invoice } var file_invoicesrpc_invoices_proto_depIdxs = []int32{ - 7, // 0: invoicesrpc.AddHoldInvoiceRequest.route_hints:type_name -> lnrpc.RouteHint + 8, // 0: invoicesrpc.AddHoldInvoiceRequest.route_hints:type_name -> lnrpc.RouteHint 6, // 1: invoicesrpc.Invoices.SubscribeSingleInvoice:input_type -> invoicesrpc.SubscribeSingleInvoiceRequest 0, // 2: invoicesrpc.Invoices.CancelInvoice:input_type -> invoicesrpc.CancelInvoiceMsg 2, // 3: invoicesrpc.Invoices.AddHoldInvoice:input_type -> invoicesrpc.AddHoldInvoiceRequest 4, // 4: invoicesrpc.Invoices.SettleInvoice:input_type -> invoicesrpc.SettleInvoiceMsg - 8, // 5: invoicesrpc.Invoices.SubscribeSingleInvoice:output_type -> lnrpc.Invoice - 1, // 6: invoicesrpc.Invoices.CancelInvoice:output_type -> invoicesrpc.CancelInvoiceResp - 3, // 7: invoicesrpc.Invoices.AddHoldInvoice:output_type -> invoicesrpc.AddHoldInvoiceResp - 5, // 8: invoicesrpc.Invoices.SettleInvoice:output_type -> invoicesrpc.SettleInvoiceResp - 5, // [5:9] is the sub-list for method output_type - 1, // [1:5] is the sub-list for method input_type + 7, // 5: invoicesrpc.Invoices.LookupInvoiceV2:input_type -> invoicesrpc.LookupInvoiceMsg + 9, // 6: invoicesrpc.Invoices.SubscribeSingleInvoice:output_type -> lnrpc.Invoice + 1, // 7: invoicesrpc.Invoices.CancelInvoice:output_type -> invoicesrpc.CancelInvoiceResp + 3, // 8: invoicesrpc.Invoices.AddHoldInvoice:output_type -> invoicesrpc.AddHoldInvoiceResp + 5, // 9: invoicesrpc.Invoices.SettleInvoice:output_type -> invoicesrpc.SettleInvoiceResp + 9, // 10: invoicesrpc.Invoices.LookupInvoiceV2:output_type -> lnrpc.Invoice + 6, // [6:11] is the sub-list for method output_type + 1, // [1:6] is the sub-list for method input_type 1, // [1:1] is the sub-list for extension type_name 1, // [1:1] is the sub-list for extension extendee 0, // [0:1] is the sub-list for field type_name @@ -669,6 +779,23 @@ func file_invoicesrpc_invoices_proto_init() { return nil } } + file_invoicesrpc_invoices_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LookupInvoiceMsg); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_invoicesrpc_invoices_proto_msgTypes[7].OneofWrappers = []interface{}{ + (*LookupInvoiceMsg_PaymentHash)(nil), + (*LookupInvoiceMsg_PaymentAddr)(nil), + (*LookupInvoiceMsg_SetId)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -676,7 +803,7 @@ func file_invoicesrpc_invoices_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_invoicesrpc_invoices_proto_rawDesc, NumEnums: 0, - NumMessages: 7, + NumMessages: 8, NumExtensions: 0, NumServices: 1, }, diff --git a/lnrpc/invoicesrpc/invoices.pb.gw.go b/lnrpc/invoicesrpc/invoices.pb.gw.go index 4cd995969..575f4849e 100644 --- a/lnrpc/invoicesrpc/invoices.pb.gw.go +++ b/lnrpc/invoicesrpc/invoices.pb.gw.go @@ -167,6 +167,42 @@ func local_request_Invoices_SettleInvoice_0(ctx context.Context, marshaler runti } +var ( + filter_Invoices_LookupInvoiceV2_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Invoices_LookupInvoiceV2_0(ctx context.Context, marshaler runtime.Marshaler, client InvoicesClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq LookupInvoiceMsg + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Invoices_LookupInvoiceV2_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.LookupInvoiceV2(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Invoices_LookupInvoiceV2_0(ctx context.Context, marshaler runtime.Marshaler, server InvoicesServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq LookupInvoiceMsg + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Invoices_LookupInvoiceV2_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.LookupInvoiceV2(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterInvoicesHandlerServer registers the http handlers for service Invoices to "mux". // UnaryRPC :call InvoicesServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -249,6 +285,29 @@ func RegisterInvoicesHandlerServer(ctx context.Context, mux *runtime.ServeMux, s }) + mux.Handle("GET", pattern_Invoices_LookupInvoiceV2_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/invoicesrpc.Invoices/LookupInvoiceV2", runtime.WithHTTPPathPattern("/v2/invoices/lookup")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Invoices_LookupInvoiceV2_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Invoices_LookupInvoiceV2_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -370,6 +429,26 @@ func RegisterInvoicesHandlerClient(ctx context.Context, mux *runtime.ServeMux, c }) + mux.Handle("GET", pattern_Invoices_LookupInvoiceV2_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/invoicesrpc.Invoices/LookupInvoiceV2", runtime.WithHTTPPathPattern("/v2/invoices/lookup")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Invoices_LookupInvoiceV2_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Invoices_LookupInvoiceV2_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -381,6 +460,8 @@ var ( pattern_Invoices_AddHoldInvoice_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v2", "invoices", "hodl"}, "")) pattern_Invoices_SettleInvoice_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v2", "invoices", "settle"}, "")) + + pattern_Invoices_LookupInvoiceV2_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v2", "invoices", "lookup"}, "")) ) var ( @@ -391,4 +472,6 @@ var ( forward_Invoices_AddHoldInvoice_0 = runtime.ForwardResponseMessage forward_Invoices_SettleInvoice_0 = runtime.ForwardResponseMessage + + forward_Invoices_LookupInvoiceV2_0 = runtime.ForwardResponseMessage ) diff --git a/lnrpc/invoicesrpc/invoices.pb.json.go b/lnrpc/invoicesrpc/invoices.pb.json.go index 3bad747ab..c8b2c00ed 100644 --- a/lnrpc/invoicesrpc/invoices.pb.json.go +++ b/lnrpc/invoicesrpc/invoices.pb.json.go @@ -139,4 +139,29 @@ func RegisterInvoicesJSONCallbacks(registry map[string]func(ctx context.Context, } callback(string(respBytes), nil) } + + registry["invoicesrpc.Invoices.LookupInvoiceV2"] = func(ctx context.Context, + conn *grpc.ClientConn, reqJSON string, callback func(string, error)) { + + req := &LookupInvoiceMsg{} + err := marshaler.Unmarshal([]byte(reqJSON), req) + if err != nil { + callback("", err) + return + } + + client := NewInvoicesClient(conn) + resp, err := client.LookupInvoiceV2(ctx, req) + if err != nil { + callback("", err) + return + } + + respBytes, err := marshaler.Marshal(resp) + if err != nil { + callback("", err) + return + } + callback(string(respBytes), nil) + } } diff --git a/lnrpc/invoicesrpc/invoices.proto b/lnrpc/invoicesrpc/invoices.proto index f0296d2c9..0df74c0cd 100644 --- a/lnrpc/invoicesrpc/invoices.proto +++ b/lnrpc/invoicesrpc/invoices.proto @@ -35,6 +35,12 @@ service Invoices { settled, this call will succeed. */ rpc SettleInvoice (SettleInvoiceMsg) returns (SettleInvoiceResp); + + /* + LookupInvoiceV2 attempts to look up at invoice. An invoice can be refrenced + using either its payment hash, payment address, or set ID. + */ + rpc LookupInvoiceV2 (LookupInvoiceMsg) returns (lnrpc.Invoice); } message CancelInvoiceMsg { @@ -135,3 +141,11 @@ message SubscribeSingleInvoiceRequest { // Hash corresponding to the (hold) invoice to subscribe to. bytes r_hash = 2; } + +message LookupInvoiceMsg { + oneof invoice_ref { + bytes payment_hash = 1; + bytes payment_addr = 2; + bytes set_id = 3; + } +} diff --git a/lnrpc/invoicesrpc/invoices.swagger.json b/lnrpc/invoicesrpc/invoices.swagger.json index 7a7d0b3f3..ed228026c 100644 --- a/lnrpc/invoicesrpc/invoices.swagger.json +++ b/lnrpc/invoicesrpc/invoices.swagger.json @@ -82,6 +82,52 @@ ] } }, + "/v2/invoices/lookup": { + "get": { + "summary": "LookupInvoiceV2 attempts to look up at invoice. An invoice can be refrenced\nusing either its payment hash, payment address, or set ID.", + "operationId": "Invoices_LookupInvoiceV2", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/lnrpcInvoice" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "payment_hash", + "in": "query", + "required": false, + "type": "string", + "format": "byte" + }, + { + "name": "payment_addr", + "in": "query", + "required": false, + "type": "string", + "format": "byte" + }, + { + "name": "set_id", + "in": "query", + "required": false, + "type": "string", + "format": "byte" + } + ], + "tags": [ + "Invoices" + ] + } + }, "/v2/invoices/settle": { "post": { "summary": "SettleInvoice settles an accepted invoice. If the invoice is already\nsettled, this call will succeed.", diff --git a/lnrpc/invoicesrpc/invoices.yaml b/lnrpc/invoicesrpc/invoices.yaml index 9b5129d0d..ef62d7f03 100644 --- a/lnrpc/invoicesrpc/invoices.yaml +++ b/lnrpc/invoicesrpc/invoices.yaml @@ -14,3 +14,5 @@ http: - selector: invoicesrpc.Invoices.SettleInvoice post: "/v2/invoices/settle" body: "*" + - selector: invoicesrpc.Invoices.LookupInvoiceV2 + get: "/v2/invoices/lookup" diff --git a/lnrpc/invoicesrpc/invoices_grpc.pb.go b/lnrpc/invoicesrpc/invoices_grpc.pb.go index cd2bf8dde..979beb71d 100644 --- a/lnrpc/invoicesrpc/invoices_grpc.pb.go +++ b/lnrpc/invoicesrpc/invoices_grpc.pb.go @@ -37,6 +37,10 @@ type InvoicesClient interface { //SettleInvoice settles an accepted invoice. If the invoice is already //settled, this call will succeed. SettleInvoice(ctx context.Context, in *SettleInvoiceMsg, opts ...grpc.CallOption) (*SettleInvoiceResp, error) + // + //LookupInvoiceV2 attempts to look up at invoice. An invoice can be refrenced + //using either its payment hash, payment address, or set ID. + LookupInvoiceV2(ctx context.Context, in *LookupInvoiceMsg, opts ...grpc.CallOption) (*lnrpc.Invoice, error) } type invoicesClient struct { @@ -106,6 +110,15 @@ func (c *invoicesClient) SettleInvoice(ctx context.Context, in *SettleInvoiceMsg return out, nil } +func (c *invoicesClient) LookupInvoiceV2(ctx context.Context, in *LookupInvoiceMsg, opts ...grpc.CallOption) (*lnrpc.Invoice, error) { + out := new(lnrpc.Invoice) + err := c.cc.Invoke(ctx, "/invoicesrpc.Invoices/LookupInvoiceV2", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // InvoicesServer is the server API for Invoices service. // All implementations must embed UnimplementedInvoicesServer // for forward compatibility @@ -128,6 +141,10 @@ type InvoicesServer interface { //SettleInvoice settles an accepted invoice. If the invoice is already //settled, this call will succeed. SettleInvoice(context.Context, *SettleInvoiceMsg) (*SettleInvoiceResp, error) + // + //LookupInvoiceV2 attempts to look up at invoice. An invoice can be refrenced + //using either its payment hash, payment address, or set ID. + LookupInvoiceV2(context.Context, *LookupInvoiceMsg) (*lnrpc.Invoice, error) mustEmbedUnimplementedInvoicesServer() } @@ -147,6 +164,9 @@ func (UnimplementedInvoicesServer) AddHoldInvoice(context.Context, *AddHoldInvoi func (UnimplementedInvoicesServer) SettleInvoice(context.Context, *SettleInvoiceMsg) (*SettleInvoiceResp, error) { return nil, status.Errorf(codes.Unimplemented, "method SettleInvoice not implemented") } +func (UnimplementedInvoicesServer) LookupInvoiceV2(context.Context, *LookupInvoiceMsg) (*lnrpc.Invoice, error) { + return nil, status.Errorf(codes.Unimplemented, "method LookupInvoiceV2 not implemented") +} func (UnimplementedInvoicesServer) mustEmbedUnimplementedInvoicesServer() {} // UnsafeInvoicesServer may be embedded to opt out of forward compatibility for this service. @@ -235,6 +255,24 @@ func _Invoices_SettleInvoice_Handler(srv interface{}, ctx context.Context, dec f return interceptor(ctx, in, info, handler) } +func _Invoices_LookupInvoiceV2_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(LookupInvoiceMsg) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InvoicesServer).LookupInvoiceV2(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/invoicesrpc.Invoices/LookupInvoiceV2", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InvoicesServer).LookupInvoiceV2(ctx, req.(*LookupInvoiceMsg)) + } + return interceptor(ctx, in, info, handler) +} + // Invoices_ServiceDesc is the grpc.ServiceDesc for Invoices service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -254,6 +292,10 @@ var Invoices_ServiceDesc = grpc.ServiceDesc{ MethodName: "SettleInvoice", Handler: _Invoices_SettleInvoice_Handler, }, + { + MethodName: "LookupInvoiceV2", + Handler: _Invoices_LookupInvoiceV2_Handler, + }, }, Streams: []grpc.StreamDesc{ { diff --git a/lnrpc/invoicesrpc/invoices_server.go b/lnrpc/invoicesrpc/invoices_server.go index 4cd2758a8..98b16a91a 100644 --- a/lnrpc/invoicesrpc/invoices_server.go +++ b/lnrpc/invoicesrpc/invoices_server.go @@ -5,11 +5,14 @@ package invoicesrpc import ( "context" + "fmt" "io/ioutil" "os" "path/filepath" "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" "gopkg.in/macaroon-bakery.v2/bakery" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" @@ -59,6 +62,10 @@ var ( Entity: "invoices", Action: "write", }}, + "/invoicesrpc.Invoices/LookupInvoiceV2": {{ + Entity: "invoices", + Action: "write", + }}, } // DefaultInvoicesMacFilename is the default name of the invoices @@ -363,3 +370,55 @@ func (s *Server) AddHoldInvoice(ctx context.Context, PaymentAddr: dbInvoice.Terms.PaymentAddr[:], }, nil } + +// LookupInvoiceV2 attempts to look up at invoice. An invoice can be referenced +// using either its payment hash, payment address, or set ID. +func (s *Server) LookupInvoiceV2(ctx context.Context, + req *LookupInvoiceMsg) (*lnrpc.Invoice, error) { + + var invoiceRef channeldb.InvoiceRef + + // First, we'll attempt to parse out the invoice ref from the proto + // oneof. If none of the three currently supported types was + // specified, then we'll exit with an error. + switch { + case req.GetPaymentHash() != nil: + payHash, err := lntypes.MakeHash(req.GetPaymentHash()) + if err != nil { + return nil, status.Error( + codes.InvalidArgument, + fmt.Sprintf("unable to parse pay hash: %v", err), + ) + } + + invoiceRef = channeldb.InvoiceRefByHash(payHash) + + case req.GetPaymentAddr() != nil: + var payAddr [32]byte + copy(payAddr[:], req.GetPaymentAddr()) + + invoiceRef = channeldb.InvoiceRefByAddr(payAddr) + + case req.GetSetId() != nil: + var setID [32]byte + copy(setID[:], req.GetSetId()) + + invoiceRef = channeldb.InvoiceRefBySetID(setID) + + default: + return nil, status.Error(codes.InvalidArgument, + "invoice ref must be set") + } + + // Attempt to locate the invoice, returning a nice "not found" error if + // we can't find it in the database. + invoice, err := s.cfg.InvoiceRegistry.LookupInvoiceByRef(invoiceRef) + switch { + case err == channeldb.ErrInvoiceNotFound: + return nil, status.Error(codes.NotFound, err.Error()) + case err != nil: + return nil, err + } + + return CreateRPCInvoice(&invoice, s.cfg.ChainParams) +}