From 67d4bad73fa185a7bb285f3ffa5e06e9215f71ff Mon Sep 17 00:00:00 2001 From: carla Date: Fri, 13 Mar 2020 09:30:16 +0200 Subject: [PATCH 1/3] rpcserver+routerrpc: add subscribe events to router backend Add SubscribeHtlcEvents to RouterBackend in preparation for the addition of a HtlcNotifier stream. --- lnrpc/routerrpc/router_backend.go | 5 +++++ rpcserver.go | 1 + 2 files changed, 6 insertions(+) diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index 120211b1..259f78f7 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -20,6 +20,7 @@ import ( "github.com/lightningnetwork/lnd/record" "github.com/lightningnetwork/lnd/routing" "github.com/lightningnetwork/lnd/routing/route" + "github.com/lightningnetwork/lnd/subscribe" "github.com/lightningnetwork/lnd/zpay32" ) @@ -68,6 +69,10 @@ type RouterBackend struct { // DefaultFinalCltvDelta is the default value used as final cltv delta // when an RPC caller doesn't specify a value. DefaultFinalCltvDelta uint16 + + // SubscribeHtlcEvents returns a subscription client for the node's + // htlc events. + SubscribeHtlcEvents func() (*subscribe.Client, error) } // MissionControl defines the mission control dependencies of routerrpc. diff --git a/rpcserver.go b/rpcserver.go index f2ea166b..9725ed55 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -567,6 +567,7 @@ func newRPCServer(s *server, macService *macaroons.Service, Tower: s.controlTower, MaxTotalTimelock: cfg.MaxOutgoingCltvExpiry, DefaultFinalCltvDelta: uint16(cfg.Bitcoin.TimeLockDelta), + SubscribeHtlcEvents: s.htlcNotifier.SubscribeHtlcEvents, } genInvoiceFeatures := func() *lnwire.FeatureVector { From aa70d5d02ab7129cb93e7b44dffbbbce4efb62e9 Mon Sep 17 00:00:00 2001 From: carla Date: Fri, 13 Mar 2020 09:30:16 +0200 Subject: [PATCH 2/3] routerrpc: add quit channel to signal shutdown --- lnrpc/routerrpc/router_server.go | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/lnrpc/routerrpc/router_server.go b/lnrpc/routerrpc/router_server.go index ed02a6fc..8bbdb387 100644 --- a/lnrpc/routerrpc/router_server.go +++ b/lnrpc/routerrpc/router_server.go @@ -9,6 +9,7 @@ import ( "io/ioutil" "os" "path/filepath" + "sync/atomic" "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd/channeldb" @@ -32,6 +33,8 @@ const ( ) var ( + errServerShuttingDown = errors.New("routerrpc server shutting down") + // macaroonOps are the set of capabilities that our minted macaroon (if // it doesn't already exist) will have. macaroonOps = []bakery.Op{ @@ -90,7 +93,12 @@ var ( // Server is a stand alone sub RPC server which exposes functionality that // allows clients to route arbitrary payment through the Lightning Network. type Server struct { + started int32 // To be used atomically. + shutdown int32 // To be used atomically. + cfg *Config + + quit chan struct{} } // A compile time check to ensure that Server fully implements the RouterServer @@ -150,7 +158,8 @@ func New(cfg *Config) (*Server, lnrpc.MacaroonPerms, error) { } routerServer := &Server{ - cfg: cfg, + cfg: cfg, + quit: make(chan struct{}), } return routerServer, macPermissions, nil @@ -160,6 +169,10 @@ func New(cfg *Config) (*Server, lnrpc.MacaroonPerms, error) { // // NOTE: This is part of the lnrpc.SubServer interface. func (s *Server) Start() error { + if atomic.AddInt32(&s.started, 1) != 1 { + return nil + } + return nil } @@ -167,6 +180,11 @@ func (s *Server) Start() error { // // NOTE: This is part of the lnrpc.SubServer interface. func (s *Server) Stop() error { + if atomic.AddInt32(&s.shutdown, 1) != 1 { + return nil + } + + close(s.quit) return nil } @@ -513,6 +531,9 @@ func (s *Server) trackPayment(paymentHash lntypes.Hash, return err } + case <-s.quit: + return errServerShuttingDown + case <-stream.Context().Done(): log.Debugf("Payment status stream %v canceled", paymentHash) return stream.Context().Err() From 0a5b918db2e0375c48bb05398dd24a6133982185 Mon Sep 17 00:00:00 2001 From: carla Date: Fri, 13 Mar 2020 09:30:16 +0200 Subject: [PATCH 3/3] routerrpc: add htlcnotifier subscription --- lnrpc/routerrpc/router.pb.go | 871 +++++++++++++++++++++++++--- lnrpc/routerrpc/router.proto | 135 +++++ lnrpc/routerrpc/router_server.go | 43 ++ lnrpc/routerrpc/subscribe_events.go | 241 ++++++++ 4 files changed, 1201 insertions(+), 89 deletions(-) create mode 100644 lnrpc/routerrpc/subscribe_events.go diff --git a/lnrpc/routerrpc/router.pb.go b/lnrpc/routerrpc/router.pb.go index 5951e4e9..ea4f940f 100644 --- a/lnrpc/routerrpc/router.pb.go +++ b/lnrpc/routerrpc/router.pb.go @@ -79,6 +79,125 @@ func (PaymentState) EnumDescriptor() ([]byte, []int) { return fileDescriptor_7a0613f69d37b0a5, []int{0} } +type FailureDetail int32 + +const ( + FailureDetail_UNKNOWN FailureDetail = 0 + FailureDetail_NO_DETAIL FailureDetail = 1 + FailureDetail_ONION_DECODE FailureDetail = 2 + FailureDetail_LINK_NOT_ELIGIBLE FailureDetail = 3 + FailureDetail_ON_CHAIN_TIMEOUT FailureDetail = 4 + FailureDetail_HTLC_EXCEEDS_MAX FailureDetail = 5 + FailureDetail_INSUFFICIENT_BALANCE FailureDetail = 6 + FailureDetail_INCOMPLETE_FORWARD FailureDetail = 7 + FailureDetail_HTLC_ADD_FAILED FailureDetail = 8 + FailureDetail_FORWARDS_DISABLED FailureDetail = 9 + FailureDetail_INVOICE_CANCELED FailureDetail = 10 + FailureDetail_INVOICE_UNDERPAID FailureDetail = 11 + FailureDetail_INVOICE_EXPIRY_TOO_SOON FailureDetail = 12 + FailureDetail_INVOICE_NOT_OPEN FailureDetail = 13 + FailureDetail_MPP_INVOICE_TIMEOUT FailureDetail = 14 + FailureDetail_ADDRESS_MISMATCH FailureDetail = 15 + FailureDetail_SET_TOTAL_MISMATCH FailureDetail = 16 + FailureDetail_SET_TOTAL_TOO_LOW FailureDetail = 17 + FailureDetail_SET_OVERPAID FailureDetail = 18 + FailureDetail_UNKNOWN_INVOICE FailureDetail = 19 + FailureDetail_INVALID_KEYSEND FailureDetail = 20 + FailureDetail_MPP_IN_PROGRESS FailureDetail = 21 + FailureDetail_CIRCULAR_ROUTE FailureDetail = 22 +) + +var FailureDetail_name = map[int32]string{ + 0: "UNKNOWN", + 1: "NO_DETAIL", + 2: "ONION_DECODE", + 3: "LINK_NOT_ELIGIBLE", + 4: "ON_CHAIN_TIMEOUT", + 5: "HTLC_EXCEEDS_MAX", + 6: "INSUFFICIENT_BALANCE", + 7: "INCOMPLETE_FORWARD", + 8: "HTLC_ADD_FAILED", + 9: "FORWARDS_DISABLED", + 10: "INVOICE_CANCELED", + 11: "INVOICE_UNDERPAID", + 12: "INVOICE_EXPIRY_TOO_SOON", + 13: "INVOICE_NOT_OPEN", + 14: "MPP_INVOICE_TIMEOUT", + 15: "ADDRESS_MISMATCH", + 16: "SET_TOTAL_MISMATCH", + 17: "SET_TOTAL_TOO_LOW", + 18: "SET_OVERPAID", + 19: "UNKNOWN_INVOICE", + 20: "INVALID_KEYSEND", + 21: "MPP_IN_PROGRESS", + 22: "CIRCULAR_ROUTE", +} + +var FailureDetail_value = map[string]int32{ + "UNKNOWN": 0, + "NO_DETAIL": 1, + "ONION_DECODE": 2, + "LINK_NOT_ELIGIBLE": 3, + "ON_CHAIN_TIMEOUT": 4, + "HTLC_EXCEEDS_MAX": 5, + "INSUFFICIENT_BALANCE": 6, + "INCOMPLETE_FORWARD": 7, + "HTLC_ADD_FAILED": 8, + "FORWARDS_DISABLED": 9, + "INVOICE_CANCELED": 10, + "INVOICE_UNDERPAID": 11, + "INVOICE_EXPIRY_TOO_SOON": 12, + "INVOICE_NOT_OPEN": 13, + "MPP_INVOICE_TIMEOUT": 14, + "ADDRESS_MISMATCH": 15, + "SET_TOTAL_MISMATCH": 16, + "SET_TOTAL_TOO_LOW": 17, + "SET_OVERPAID": 18, + "UNKNOWN_INVOICE": 19, + "INVALID_KEYSEND": 20, + "MPP_IN_PROGRESS": 21, + "CIRCULAR_ROUTE": 22, +} + +func (x FailureDetail) String() string { + return proto.EnumName(FailureDetail_name, int32(x)) +} + +func (FailureDetail) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_7a0613f69d37b0a5, []int{1} +} + +type HtlcEvent_EventType int32 + +const ( + HtlcEvent_UNKNOWN HtlcEvent_EventType = 0 + HtlcEvent_SEND HtlcEvent_EventType = 1 + HtlcEvent_RECEIVE HtlcEvent_EventType = 2 + HtlcEvent_FORWARD HtlcEvent_EventType = 3 +) + +var HtlcEvent_EventType_name = map[int32]string{ + 0: "UNKNOWN", + 1: "SEND", + 2: "RECEIVE", + 3: "FORWARD", +} + +var HtlcEvent_EventType_value = map[string]int32{ + "UNKNOWN": 0, + "SEND": 1, + "RECEIVE": 2, + "FORWARD": 3, +} + +func (x HtlcEvent_EventType) String() string { + return proto.EnumName(HtlcEvent_EventType_name, int32(x)) +} + +func (HtlcEvent_EventType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_7a0613f69d37b0a5, []int{18, 0} +} + type SendPaymentRequest struct { /// The identity pubkey of the payment recipient Dest []byte `protobuf:"bytes,1,opt,name=dest,proto3" json:"dest,omitempty"` @@ -1118,8 +1237,462 @@ func (m *BuildRouteResponse) GetRoute() *lnrpc.Route { return nil } +type SubscribeHtlcEventsRequest struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SubscribeHtlcEventsRequest) Reset() { *m = SubscribeHtlcEventsRequest{} } +func (m *SubscribeHtlcEventsRequest) String() string { return proto.CompactTextString(m) } +func (*SubscribeHtlcEventsRequest) ProtoMessage() {} +func (*SubscribeHtlcEventsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_7a0613f69d37b0a5, []int{17} +} + +func (m *SubscribeHtlcEventsRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SubscribeHtlcEventsRequest.Unmarshal(m, b) +} +func (m *SubscribeHtlcEventsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SubscribeHtlcEventsRequest.Marshal(b, m, deterministic) +} +func (m *SubscribeHtlcEventsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_SubscribeHtlcEventsRequest.Merge(m, src) +} +func (m *SubscribeHtlcEventsRequest) XXX_Size() int { + return xxx_messageInfo_SubscribeHtlcEventsRequest.Size(m) +} +func (m *SubscribeHtlcEventsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_SubscribeHtlcEventsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_SubscribeHtlcEventsRequest proto.InternalMessageInfo + +//* +//HtlcEvent contains the htlc event that was processed. These are served on a +//best-effort basis; events are not persisted, delivery is not guaranteed +//(in the event of a crash in the switch, forward events may be lost) and +//some events may be replayed upon restart. Events consumed from this package +//should be de-duplicated by the htlc's unique combination of incoming and +//outgoing channel id and htlc id. [EXPERIMENTAL] +type HtlcEvent struct { + //* + //The short channel id that the incoming htlc arrived at our node on. This + //value is zero for sends. + IncomingChannelId uint64 `protobuf:"varint,1,opt,name=incoming_channel_id,json=incomingChannelId,proto3" json:"incoming_channel_id,omitempty"` + //* + //The short channel id that the outgoing htlc left our node on. This value + //is zero for receives. + OutgoingChannelId uint64 `protobuf:"varint,2,opt,name=outgoing_channel_id,json=outgoingChannelId,proto3" json:"outgoing_channel_id,omitempty"` + //* + //Incoming id is the index of the incoming htlc in the incoming channel. + //This value is zero for sends. + IncomingHtlcId uint64 `protobuf:"varint,3,opt,name=incoming_htlc_id,json=incomingHtlcId,proto3" json:"incoming_htlc_id,omitempty"` + //* + //Outgoing id is the index of the outgoing htlc in the outgoing channel. + //This value is zero for receives. + OutgoingHtlcId uint64 `protobuf:"varint,4,opt,name=outgoing_htlc_id,json=outgoingHtlcId,proto3" json:"outgoing_htlc_id,omitempty"` + //* + //The time in unix nanoseconds that the event occurred. + TimestampNs uint64 `protobuf:"varint,5,opt,name=timestamp_ns,json=timestampNs,proto3" json:"timestamp_ns,omitempty"` + //* + //The event type indicates whether the htlc was part of a send, receive or + //forward. + EventType HtlcEvent_EventType `protobuf:"varint,6,opt,name=event_type,json=eventType,proto3,enum=routerrpc.HtlcEvent_EventType" json:"event_type,omitempty"` + // Types that are valid to be assigned to Event: + // *HtlcEvent_ForwardEvent + // *HtlcEvent_ForwardFailEvent + // *HtlcEvent_SettleEvent + // *HtlcEvent_LinkFailEvent + Event isHtlcEvent_Event `protobuf_oneof:"event"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *HtlcEvent) Reset() { *m = HtlcEvent{} } +func (m *HtlcEvent) String() string { return proto.CompactTextString(m) } +func (*HtlcEvent) ProtoMessage() {} +func (*HtlcEvent) Descriptor() ([]byte, []int) { + return fileDescriptor_7a0613f69d37b0a5, []int{18} +} + +func (m *HtlcEvent) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_HtlcEvent.Unmarshal(m, b) +} +func (m *HtlcEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_HtlcEvent.Marshal(b, m, deterministic) +} +func (m *HtlcEvent) XXX_Merge(src proto.Message) { + xxx_messageInfo_HtlcEvent.Merge(m, src) +} +func (m *HtlcEvent) XXX_Size() int { + return xxx_messageInfo_HtlcEvent.Size(m) +} +func (m *HtlcEvent) XXX_DiscardUnknown() { + xxx_messageInfo_HtlcEvent.DiscardUnknown(m) +} + +var xxx_messageInfo_HtlcEvent proto.InternalMessageInfo + +func (m *HtlcEvent) GetIncomingChannelId() uint64 { + if m != nil { + return m.IncomingChannelId + } + return 0 +} + +func (m *HtlcEvent) GetOutgoingChannelId() uint64 { + if m != nil { + return m.OutgoingChannelId + } + return 0 +} + +func (m *HtlcEvent) GetIncomingHtlcId() uint64 { + if m != nil { + return m.IncomingHtlcId + } + return 0 +} + +func (m *HtlcEvent) GetOutgoingHtlcId() uint64 { + if m != nil { + return m.OutgoingHtlcId + } + return 0 +} + +func (m *HtlcEvent) GetTimestampNs() uint64 { + if m != nil { + return m.TimestampNs + } + return 0 +} + +func (m *HtlcEvent) GetEventType() HtlcEvent_EventType { + if m != nil { + return m.EventType + } + return HtlcEvent_UNKNOWN +} + +type isHtlcEvent_Event interface { + isHtlcEvent_Event() +} + +type HtlcEvent_ForwardEvent struct { + ForwardEvent *ForwardEvent `protobuf:"bytes,7,opt,name=forward_event,json=forwardEvent,proto3,oneof"` +} + +type HtlcEvent_ForwardFailEvent struct { + ForwardFailEvent *ForwardFailEvent `protobuf:"bytes,8,opt,name=forward_fail_event,json=forwardFailEvent,proto3,oneof"` +} + +type HtlcEvent_SettleEvent struct { + SettleEvent *SettleEvent `protobuf:"bytes,9,opt,name=settle_event,json=settleEvent,proto3,oneof"` +} + +type HtlcEvent_LinkFailEvent struct { + LinkFailEvent *LinkFailEvent `protobuf:"bytes,10,opt,name=link_fail_event,json=linkFailEvent,proto3,oneof"` +} + +func (*HtlcEvent_ForwardEvent) isHtlcEvent_Event() {} + +func (*HtlcEvent_ForwardFailEvent) isHtlcEvent_Event() {} + +func (*HtlcEvent_SettleEvent) isHtlcEvent_Event() {} + +func (*HtlcEvent_LinkFailEvent) isHtlcEvent_Event() {} + +func (m *HtlcEvent) GetEvent() isHtlcEvent_Event { + if m != nil { + return m.Event + } + return nil +} + +func (m *HtlcEvent) GetForwardEvent() *ForwardEvent { + if x, ok := m.GetEvent().(*HtlcEvent_ForwardEvent); ok { + return x.ForwardEvent + } + return nil +} + +func (m *HtlcEvent) GetForwardFailEvent() *ForwardFailEvent { + if x, ok := m.GetEvent().(*HtlcEvent_ForwardFailEvent); ok { + return x.ForwardFailEvent + } + return nil +} + +func (m *HtlcEvent) GetSettleEvent() *SettleEvent { + if x, ok := m.GetEvent().(*HtlcEvent_SettleEvent); ok { + return x.SettleEvent + } + return nil +} + +func (m *HtlcEvent) GetLinkFailEvent() *LinkFailEvent { + if x, ok := m.GetEvent().(*HtlcEvent_LinkFailEvent); ok { + return x.LinkFailEvent + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*HtlcEvent) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*HtlcEvent_ForwardEvent)(nil), + (*HtlcEvent_ForwardFailEvent)(nil), + (*HtlcEvent_SettleEvent)(nil), + (*HtlcEvent_LinkFailEvent)(nil), + } +} + +type HtlcInfo struct { + // The timelock on the incoming htlc. + IncomingTimelock uint32 `protobuf:"varint,1,opt,name=incoming_timelock,json=incomingTimelock,proto3" json:"incoming_timelock,omitempty"` + // The timelock on the outgoing htlc. + OutgoingTimelock uint32 `protobuf:"varint,2,opt,name=outgoing_timelock,json=outgoingTimelock,proto3" json:"outgoing_timelock,omitempty"` + // The amount of the incoming htlc. + IncomingAmtMsat uint64 `protobuf:"varint,3,opt,name=incoming_amt_msat,json=incomingAmtMsat,proto3" json:"incoming_amt_msat,omitempty"` + // The amount of the outgoing htlc. + OutgoingAmtMsat uint64 `protobuf:"varint,4,opt,name=outgoing_amt_msat,json=outgoingAmtMsat,proto3" json:"outgoing_amt_msat,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *HtlcInfo) Reset() { *m = HtlcInfo{} } +func (m *HtlcInfo) String() string { return proto.CompactTextString(m) } +func (*HtlcInfo) ProtoMessage() {} +func (*HtlcInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_7a0613f69d37b0a5, []int{19} +} + +func (m *HtlcInfo) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_HtlcInfo.Unmarshal(m, b) +} +func (m *HtlcInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_HtlcInfo.Marshal(b, m, deterministic) +} +func (m *HtlcInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_HtlcInfo.Merge(m, src) +} +func (m *HtlcInfo) XXX_Size() int { + return xxx_messageInfo_HtlcInfo.Size(m) +} +func (m *HtlcInfo) XXX_DiscardUnknown() { + xxx_messageInfo_HtlcInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_HtlcInfo proto.InternalMessageInfo + +func (m *HtlcInfo) GetIncomingTimelock() uint32 { + if m != nil { + return m.IncomingTimelock + } + return 0 +} + +func (m *HtlcInfo) GetOutgoingTimelock() uint32 { + if m != nil { + return m.OutgoingTimelock + } + return 0 +} + +func (m *HtlcInfo) GetIncomingAmtMsat() uint64 { + if m != nil { + return m.IncomingAmtMsat + } + return 0 +} + +func (m *HtlcInfo) GetOutgoingAmtMsat() uint64 { + if m != nil { + return m.OutgoingAmtMsat + } + return 0 +} + +type ForwardEvent struct { + // Info contains details about the htlc that was forwarded. + Info *HtlcInfo `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ForwardEvent) Reset() { *m = ForwardEvent{} } +func (m *ForwardEvent) String() string { return proto.CompactTextString(m) } +func (*ForwardEvent) ProtoMessage() {} +func (*ForwardEvent) Descriptor() ([]byte, []int) { + return fileDescriptor_7a0613f69d37b0a5, []int{20} +} + +func (m *ForwardEvent) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ForwardEvent.Unmarshal(m, b) +} +func (m *ForwardEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ForwardEvent.Marshal(b, m, deterministic) +} +func (m *ForwardEvent) XXX_Merge(src proto.Message) { + xxx_messageInfo_ForwardEvent.Merge(m, src) +} +func (m *ForwardEvent) XXX_Size() int { + return xxx_messageInfo_ForwardEvent.Size(m) +} +func (m *ForwardEvent) XXX_DiscardUnknown() { + xxx_messageInfo_ForwardEvent.DiscardUnknown(m) +} + +var xxx_messageInfo_ForwardEvent proto.InternalMessageInfo + +func (m *ForwardEvent) GetInfo() *HtlcInfo { + if m != nil { + return m.Info + } + return nil +} + +type ForwardFailEvent struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ForwardFailEvent) Reset() { *m = ForwardFailEvent{} } +func (m *ForwardFailEvent) String() string { return proto.CompactTextString(m) } +func (*ForwardFailEvent) ProtoMessage() {} +func (*ForwardFailEvent) Descriptor() ([]byte, []int) { + return fileDescriptor_7a0613f69d37b0a5, []int{21} +} + +func (m *ForwardFailEvent) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ForwardFailEvent.Unmarshal(m, b) +} +func (m *ForwardFailEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ForwardFailEvent.Marshal(b, m, deterministic) +} +func (m *ForwardFailEvent) XXX_Merge(src proto.Message) { + xxx_messageInfo_ForwardFailEvent.Merge(m, src) +} +func (m *ForwardFailEvent) XXX_Size() int { + return xxx_messageInfo_ForwardFailEvent.Size(m) +} +func (m *ForwardFailEvent) XXX_DiscardUnknown() { + xxx_messageInfo_ForwardFailEvent.DiscardUnknown(m) +} + +var xxx_messageInfo_ForwardFailEvent proto.InternalMessageInfo + +type SettleEvent struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SettleEvent) Reset() { *m = SettleEvent{} } +func (m *SettleEvent) String() string { return proto.CompactTextString(m) } +func (*SettleEvent) ProtoMessage() {} +func (*SettleEvent) Descriptor() ([]byte, []int) { + return fileDescriptor_7a0613f69d37b0a5, []int{22} +} + +func (m *SettleEvent) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SettleEvent.Unmarshal(m, b) +} +func (m *SettleEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SettleEvent.Marshal(b, m, deterministic) +} +func (m *SettleEvent) XXX_Merge(src proto.Message) { + xxx_messageInfo_SettleEvent.Merge(m, src) +} +func (m *SettleEvent) XXX_Size() int { + return xxx_messageInfo_SettleEvent.Size(m) +} +func (m *SettleEvent) XXX_DiscardUnknown() { + xxx_messageInfo_SettleEvent.DiscardUnknown(m) +} + +var xxx_messageInfo_SettleEvent proto.InternalMessageInfo + +type LinkFailEvent struct { + // Info contains details about the htlc that we failed. + Info *HtlcInfo `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"` + // FailureCode is the BOLT error code for the failure. + WireFailure lnrpc.Failure_FailureCode `protobuf:"varint,2,opt,name=wire_failure,json=wireFailure,proto3,enum=lnrpc.Failure_FailureCode" json:"wire_failure,omitempty"` + //* + //FailureDetail provides additional information about the reason for the + //failure. This detail enriches the information provided by the wire message + //and may be 'no detail' if the wire message requires no additional metadata. + FailureDetail FailureDetail `protobuf:"varint,3,opt,name=failure_detail,json=failureDetail,proto3,enum=routerrpc.FailureDetail" json:"failure_detail,omitempty"` + // A string representation of the link failure. + FailureString string `protobuf:"bytes,4,opt,name=failure_string,json=failureString,proto3" json:"failure_string,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *LinkFailEvent) Reset() { *m = LinkFailEvent{} } +func (m *LinkFailEvent) String() string { return proto.CompactTextString(m) } +func (*LinkFailEvent) ProtoMessage() {} +func (*LinkFailEvent) Descriptor() ([]byte, []int) { + return fileDescriptor_7a0613f69d37b0a5, []int{23} +} + +func (m *LinkFailEvent) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_LinkFailEvent.Unmarshal(m, b) +} +func (m *LinkFailEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_LinkFailEvent.Marshal(b, m, deterministic) +} +func (m *LinkFailEvent) XXX_Merge(src proto.Message) { + xxx_messageInfo_LinkFailEvent.Merge(m, src) +} +func (m *LinkFailEvent) XXX_Size() int { + return xxx_messageInfo_LinkFailEvent.Size(m) +} +func (m *LinkFailEvent) XXX_DiscardUnknown() { + xxx_messageInfo_LinkFailEvent.DiscardUnknown(m) +} + +var xxx_messageInfo_LinkFailEvent proto.InternalMessageInfo + +func (m *LinkFailEvent) GetInfo() *HtlcInfo { + if m != nil { + return m.Info + } + return nil +} + +func (m *LinkFailEvent) GetWireFailure() lnrpc.Failure_FailureCode { + if m != nil { + return m.WireFailure + } + return lnrpc.Failure_RESERVED +} + +func (m *LinkFailEvent) GetFailureDetail() FailureDetail { + if m != nil { + return m.FailureDetail + } + return FailureDetail_UNKNOWN +} + +func (m *LinkFailEvent) GetFailureString() string { + if m != nil { + return m.FailureString + } + return "" +} + func init() { proto.RegisterEnum("routerrpc.PaymentState", PaymentState_name, PaymentState_value) + proto.RegisterEnum("routerrpc.FailureDetail", FailureDetail_name, FailureDetail_value) + proto.RegisterEnum("routerrpc.HtlcEvent_EventType", HtlcEvent_EventType_name, HtlcEvent_EventType_value) proto.RegisterType((*SendPaymentRequest)(nil), "routerrpc.SendPaymentRequest") proto.RegisterMapType((map[uint64][]byte)(nil), "routerrpc.SendPaymentRequest.DestCustomRecordsEntry") proto.RegisterType((*TrackPaymentRequest)(nil), "routerrpc.TrackPaymentRequest") @@ -1138,100 +1711,154 @@ func init() { proto.RegisterType((*QueryProbabilityResponse)(nil), "routerrpc.QueryProbabilityResponse") proto.RegisterType((*BuildRouteRequest)(nil), "routerrpc.BuildRouteRequest") proto.RegisterType((*BuildRouteResponse)(nil), "routerrpc.BuildRouteResponse") + proto.RegisterType((*SubscribeHtlcEventsRequest)(nil), "routerrpc.SubscribeHtlcEventsRequest") + proto.RegisterType((*HtlcEvent)(nil), "routerrpc.HtlcEvent") + proto.RegisterType((*HtlcInfo)(nil), "routerrpc.HtlcInfo") + proto.RegisterType((*ForwardEvent)(nil), "routerrpc.ForwardEvent") + proto.RegisterType((*ForwardFailEvent)(nil), "routerrpc.ForwardFailEvent") + proto.RegisterType((*SettleEvent)(nil), "routerrpc.SettleEvent") + proto.RegisterType((*LinkFailEvent)(nil), "routerrpc.LinkFailEvent") } func init() { proto.RegisterFile("routerrpc/router.proto", fileDescriptor_7a0613f69d37b0a5) } var fileDescriptor_7a0613f69d37b0a5 = []byte{ - // 1404 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x57, 0xdb, 0x52, 0xdb, 0xd6, - 0x1a, 0xde, 0xf2, 0x09, 0xf3, 0xdb, 0x18, 0x65, 0xb1, 0x27, 0xd1, 0x36, 0x21, 0xf1, 0xd6, 0xce, - 0x26, 0x9e, 0x4e, 0x02, 0x09, 0xed, 0x74, 0x32, 0xbd, 0xe8, 0x0c, 0xf8, 0x50, 0x4c, 0xcd, 0x21, - 0xcb, 0xe6, 0xa2, 0xcd, 0x85, 0x46, 0x58, 0xcb, 0x58, 0x45, 0xd2, 0x72, 0xb5, 0x96, 0x92, 0xe1, - 0x15, 0xfa, 0x22, 0xed, 0x4d, 0xfb, 0x5c, 0x7d, 0x84, 0x5e, 0x76, 0xd6, 0x41, 0x58, 0x36, 0x36, - 0xe9, 0x9d, 0xf5, 0xfd, 0xdf, 0x7f, 0x5a, 0xff, 0x09, 0xe0, 0x71, 0x4c, 0x13, 0x4e, 0xe2, 0x78, - 0x3a, 0xda, 0x57, 0xbf, 0xf6, 0xa6, 0x31, 0xe5, 0x14, 0xad, 0xdf, 0xe1, 0xf5, 0xf5, 0x78, 0x3a, - 0x52, 0xa8, 0xfd, 0x57, 0x11, 0xd0, 0x80, 0x44, 0xde, 0x85, 0x7b, 0x1b, 0x92, 0x88, 0x63, 0xf2, - 0x73, 0x42, 0x18, 0x47, 0x08, 0x0a, 0x1e, 0x61, 0xdc, 0x32, 0x1a, 0x46, 0xb3, 0x8a, 0xe5, 0x6f, - 0x64, 0x42, 0xde, 0x0d, 0xb9, 0x95, 0x6b, 0x18, 0xcd, 0x3c, 0x16, 0x3f, 0xd1, 0x7f, 0xa0, 0xec, - 0x86, 0xdc, 0x09, 0x99, 0xcb, 0xad, 0xaa, 0x84, 0xd7, 0xdc, 0x90, 0x9f, 0x32, 0x97, 0xa3, 0xff, - 0x42, 0x75, 0xaa, 0x4c, 0x3a, 0x13, 0x97, 0x4d, 0xac, 0xbc, 0x34, 0x54, 0xd1, 0xd8, 0xb1, 0xcb, - 0x26, 0xa8, 0x09, 0xe6, 0xd8, 0x8f, 0xdc, 0xc0, 0x19, 0x05, 0xfc, 0xa3, 0xe3, 0x91, 0x80, 0xbb, - 0x56, 0xa1, 0x61, 0x34, 0x8b, 0xb8, 0x26, 0xf1, 0x56, 0xc0, 0x3f, 0xb6, 0x05, 0x8a, 0x5e, 0xc2, - 0x66, 0x6a, 0x2c, 0x56, 0x01, 0x5a, 0xc5, 0x86, 0xd1, 0x5c, 0xc7, 0xb5, 0xe9, 0x7c, 0xd8, 0x2f, - 0x61, 0x93, 0xfb, 0x21, 0xa1, 0x09, 0x77, 0x18, 0x19, 0xd1, 0xc8, 0x63, 0x56, 0x49, 0x59, 0xd4, - 0xf0, 0x40, 0xa1, 0xc8, 0x86, 0x8d, 0x31, 0x21, 0x4e, 0xe0, 0x87, 0x3e, 0x77, 0x44, 0xf8, 0x6b, - 0x32, 0xfc, 0xca, 0x98, 0x90, 0xbe, 0xc0, 0x06, 0x2e, 0x47, 0x2f, 0xa0, 0x36, 0xe3, 0xc8, 0x1c, - 0x37, 0x24, 0xa9, 0x9a, 0x92, 0x64, 0xa2, 0xaf, 0xc0, 0xa4, 0x09, 0xbf, 0xa6, 0x7e, 0x74, 0xed, - 0x8c, 0x26, 0x6e, 0xe4, 0xf8, 0x9e, 0x55, 0x6e, 0x18, 0xcd, 0xc2, 0x51, 0xee, 0x8d, 0x81, 0x6b, - 0xa9, 0xac, 0x35, 0x71, 0xa3, 0x9e, 0x87, 0x76, 0x61, 0x33, 0x70, 0x19, 0x77, 0x26, 0x74, 0xea, - 0x4c, 0x93, 0xab, 0x1b, 0x72, 0x6b, 0xd5, 0xe4, 0xcb, 0x6c, 0x08, 0xf8, 0x98, 0x4e, 0x2f, 0x24, - 0x88, 0x76, 0x00, 0xe4, 0xab, 0x48, 0xe7, 0xd6, 0xba, 0xcc, 0x61, 0x5d, 0x20, 0xd2, 0x31, 0x7a, - 0x0b, 0x15, 0x59, 0x4d, 0x67, 0xe2, 0x47, 0x9c, 0x59, 0xd0, 0xc8, 0x37, 0x2b, 0x07, 0xe6, 0x5e, - 0x10, 0x89, 0xc2, 0x62, 0x21, 0x39, 0xf6, 0x23, 0x8e, 0x21, 0x4e, 0x7f, 0x32, 0xe4, 0xc1, 0x96, - 0xa8, 0xa2, 0x33, 0x4a, 0x18, 0xa7, 0xa1, 0x13, 0x93, 0x11, 0x8d, 0x3d, 0x66, 0x55, 0xa4, 0xea, - 0x57, 0x7b, 0x77, 0xcd, 0xb1, 0x77, 0xbf, 0x1b, 0xf6, 0xda, 0x84, 0xf1, 0x96, 0xd4, 0xc3, 0x4a, - 0xad, 0x13, 0xf1, 0xf8, 0x16, 0x3f, 0xf2, 0x16, 0x71, 0xf4, 0x0a, 0x90, 0x1b, 0x04, 0xf4, 0x93, - 0xc3, 0x48, 0x30, 0x76, 0x74, 0x75, 0xac, 0xcd, 0x86, 0xd1, 0x2c, 0x63, 0x53, 0x4a, 0x06, 0x24, - 0x18, 0x6b, 0xf3, 0xe8, 0x6b, 0xd8, 0x90, 0x31, 0x8d, 0x89, 0xcb, 0x93, 0x98, 0x30, 0xcb, 0x6c, - 0xe4, 0x9b, 0xb5, 0x83, 0x47, 0x3a, 0x91, 0xae, 0x82, 0x8f, 0x7c, 0x8e, 0xab, 0x82, 0xa7, 0xbf, - 0x59, 0xbd, 0x0d, 0x8f, 0x97, 0x87, 0x24, 0x7a, 0x54, 0xbc, 0xa9, 0x68, 0xdb, 0x02, 0x16, 0x3f, - 0xd1, 0xbf, 0xa1, 0xf8, 0xd1, 0x0d, 0x12, 0x22, 0xfb, 0xb6, 0x8a, 0xd5, 0xc7, 0x37, 0xb9, 0x77, - 0x86, 0xfd, 0x0e, 0xb6, 0x86, 0xb1, 0x3b, 0xba, 0x59, 0x68, 0xfd, 0xc5, 0xce, 0x35, 0xee, 0x75, - 0xae, 0xfd, 0x9b, 0x01, 0x1b, 0x5a, 0x6b, 0xc0, 0x5d, 0x9e, 0x30, 0xf4, 0x1a, 0x8a, 0x8c, 0xbb, - 0x9c, 0x48, 0x76, 0xed, 0xe0, 0x49, 0xe6, 0x3d, 0x33, 0x44, 0x82, 0x15, 0x0b, 0xd5, 0xa1, 0x3c, - 0x8d, 0x89, 0x1f, 0xba, 0xd7, 0x69, 0x5c, 0x77, 0xdf, 0xc8, 0x86, 0xa2, 0x54, 0x96, 0x23, 0x53, - 0x39, 0xa8, 0x66, 0xab, 0x8a, 0x95, 0x08, 0x35, 0xa1, 0x38, 0xe1, 0xc1, 0x88, 0x59, 0x05, 0x59, - 0x3e, 0xa4, 0x39, 0xc7, 0xc3, 0x7e, 0xeb, 0x90, 0x73, 0x12, 0x4e, 0x39, 0x56, 0x04, 0xfb, 0x5b, - 0xd8, 0x94, 0x9a, 0x5d, 0x42, 0x1e, 0x9a, 0xed, 0x27, 0x20, 0x26, 0x57, 0x4e, 0x82, 0x9a, 0xef, - 0x92, 0x1b, 0x8a, 0x21, 0xb0, 0x3d, 0x30, 0x67, 0xfa, 0x6c, 0x4a, 0x23, 0x26, 0xbc, 0x9b, 0x22, - 0x0c, 0xd1, 0xf1, 0x62, 0x40, 0xe4, 0x68, 0x18, 0x52, 0xab, 0xa6, 0xf1, 0x2e, 0x21, 0x72, 0x38, - 0x76, 0xd5, 0x3c, 0x3a, 0x01, 0x1d, 0xdd, 0x88, 0x09, 0x77, 0x6f, 0xb5, 0xf9, 0x0d, 0x01, 0xf7, - 0xe9, 0xe8, 0xa6, 0x2d, 0x40, 0xfb, 0x83, 0x5a, 0x42, 0x43, 0xaa, 0xb2, 0xfc, 0xc7, 0x95, 0x98, - 0x3d, 0x56, 0x6e, 0xe5, 0x63, 0xd9, 0x1f, 0x60, 0x6b, 0xce, 0xb8, 0xce, 0x22, 0x5b, 0x03, 0x63, - 0xa1, 0x06, 0x4d, 0x58, 0x1b, 0xbb, 0x7e, 0x90, 0xc4, 0xa9, 0xe1, 0x5a, 0xda, 0x92, 0x0a, 0xc5, - 0xa9, 0xd8, 0x7e, 0x0a, 0x75, 0x4c, 0x18, 0xe1, 0xa7, 0x3e, 0x63, 0x3e, 0x8d, 0x5a, 0x34, 0xe2, - 0x31, 0x0d, 0x74, 0x06, 0xf6, 0x0e, 0x6c, 0x2f, 0x95, 0xaa, 0x10, 0x84, 0xf2, 0xfb, 0x84, 0xc4, - 0xb7, 0xcb, 0x95, 0xdf, 0xc3, 0xf6, 0x52, 0xa9, 0x8e, 0xff, 0x15, 0x14, 0xa7, 0xae, 0x1f, 0x33, - 0x2b, 0x27, 0x7b, 0xe0, 0xf1, 0x5c, 0xcb, 0xf9, 0xf1, 0xb1, 0xcf, 0x38, 0x8d, 0x6f, 0xb1, 0x22, - 0x9d, 0x14, 0xca, 0x86, 0x99, 0xb3, 0x7f, 0x31, 0xa0, 0x92, 0x11, 0xa2, 0x6d, 0x58, 0x8f, 0xa8, - 0x47, 0x9c, 0x71, 0x4c, 0xc3, 0xf4, 0x11, 0x04, 0xd0, 0x8d, 0x69, 0x28, 0x7a, 0x42, 0x0a, 0x39, - 0xd5, 0x3d, 0x5a, 0x12, 0x9f, 0x43, 0x8a, 0x5e, 0xc3, 0xda, 0x44, 0x19, 0x90, 0x6b, 0xb3, 0x72, - 0xb0, 0xb5, 0xe0, 0xbb, 0xed, 0x72, 0x17, 0xa7, 0x9c, 0x93, 0x42, 0x39, 0x6f, 0x16, 0x4e, 0x0a, - 0xe5, 0x82, 0x59, 0x3c, 0x29, 0x94, 0x8b, 0x66, 0xe9, 0xa4, 0x50, 0x2e, 0x99, 0x6b, 0xf6, 0x9f, - 0x06, 0x94, 0x53, 0xb6, 0x88, 0x44, 0x3c, 0xa9, 0x23, 0xfa, 0x42, 0x37, 0x53, 0x59, 0x00, 0x43, - 0x3f, 0x24, 0xa8, 0x01, 0x55, 0x29, 0x9c, 0x6f, 0x51, 0x10, 0xd8, 0xa1, 0x6c, 0x53, 0xb9, 0xcf, - 0x53, 0x86, 0xec, 0xc7, 0x82, 0xde, 0xe7, 0x8a, 0x92, 0x9e, 0x24, 0x96, 0x8c, 0x46, 0x84, 0x31, - 0xe5, 0xa5, 0xa8, 0x28, 0x1a, 0x93, 0x8e, 0x76, 0x61, 0x33, 0xa5, 0xa4, 0xbe, 0x4a, 0xaa, 0x5f, - 0x35, 0xac, 0xdd, 0x35, 0xc1, 0xcc, 0xf2, 0xc2, 0xd9, 0x05, 0xa9, 0xcd, 0x88, 0xc2, 0xa9, 0x4a, - 0xde, 0xfe, 0x09, 0x9e, 0xc8, 0x52, 0x5e, 0xc4, 0xf4, 0xca, 0xbd, 0xf2, 0x03, 0x9f, 0xdf, 0xa6, - 0x4d, 0x2e, 0x12, 0x8f, 0x69, 0xe8, 0x88, 0xb7, 0x4d, 0x4b, 0x20, 0x80, 0x33, 0xea, 0x11, 0x51, - 0x02, 0x4e, 0x95, 0x48, 0x97, 0x80, 0x53, 0x29, 0xc8, 0x5e, 0xde, 0xfc, 0xdc, 0xe5, 0xb5, 0x6f, - 0xc0, 0xba, 0xef, 0x4b, 0xf7, 0x4c, 0x03, 0x2a, 0xd3, 0x19, 0x2c, 0xdd, 0x19, 0x38, 0x0b, 0x65, - 0x6b, 0x9b, 0xfb, 0x7c, 0x6d, 0xed, 0x5f, 0x0d, 0x78, 0x74, 0x94, 0xf8, 0x81, 0x37, 0x37, 0xb8, - 0xd9, 0xe8, 0x8c, 0xf9, 0xbf, 0x0b, 0x96, 0x1d, 0xfd, 0xdc, 0xd2, 0xa3, 0xbf, 0xec, 0xb0, 0xe6, - 0x57, 0x1e, 0xd6, 0xe7, 0x50, 0x99, 0xdd, 0x54, 0xb5, 0x17, 0xab, 0x18, 0x26, 0xe9, 0x41, 0x65, - 0xf6, 0x3b, 0x40, 0xd9, 0x40, 0xf5, 0x83, 0xdc, 0xed, 0x0f, 0x63, 0xe5, 0xfe, 0xf8, 0xe2, 0x0f, - 0x03, 0xaa, 0xd9, 0x25, 0x8e, 0x36, 0x60, 0xbd, 0x77, 0xe6, 0x74, 0xfb, 0xbd, 0xef, 0x8e, 0x87, - 0xe6, 0xbf, 0xc4, 0xe7, 0xe0, 0xb2, 0xd5, 0xea, 0x74, 0xda, 0x9d, 0xb6, 0x69, 0x20, 0x04, 0xb5, - 0xee, 0x61, 0xaf, 0xdf, 0x69, 0x3b, 0xc3, 0xde, 0x69, 0xe7, 0xfc, 0x72, 0x68, 0xe6, 0xd0, 0x16, - 0x6c, 0x6a, 0xec, 0xec, 0xdc, 0xc1, 0xe7, 0x97, 0xc3, 0x8e, 0x99, 0x47, 0x26, 0x54, 0x35, 0xd8, - 0xc1, 0xf8, 0x1c, 0x9b, 0x05, 0xf4, 0x02, 0x1a, 0x1a, 0xe9, 0x9d, 0xb5, 0xce, 0x31, 0xee, 0xb4, - 0x86, 0xce, 0xc5, 0xe1, 0x0f, 0xa7, 0x9d, 0xb3, 0xa1, 0xd3, 0xee, 0x0c, 0x0f, 0x7b, 0xfd, 0x81, - 0x59, 0x44, 0xcf, 0x61, 0xfb, 0x8e, 0x35, 0xb8, 0xec, 0x76, 0x7b, 0xad, 0x9e, 0x20, 0x1c, 0x1d, - 0xf6, 0x0f, 0xcf, 0x5a, 0x1d, 0xb3, 0x74, 0xf0, 0x7b, 0x11, 0x4a, 0x32, 0x83, 0x18, 0x1d, 0x43, - 0x25, 0x73, 0xcf, 0xd1, 0xce, 0x83, 0x77, 0xbe, 0x6e, 0x2d, 0x3f, 0x5b, 0x09, 0x7b, 0x63, 0xa0, - 0x13, 0xa8, 0x66, 0xaf, 0x25, 0x7a, 0x96, 0xe1, 0x2e, 0x39, 0xa3, 0x0f, 0xda, 0xfa, 0x1e, 0xcc, - 0x0e, 0xe3, 0x7e, 0x28, 0x2e, 0xa2, 0x3e, 0x2e, 0xa8, 0x9e, 0xe1, 0x2f, 0x5c, 0xac, 0xfa, 0xf6, - 0x52, 0x99, 0x2e, 0x61, 0x5f, 0xa5, 0xa8, 0xd7, 0xfb, 0xbd, 0x14, 0xe7, 0x6f, 0x4a, 0xfd, 0xd9, - 0x2a, 0xb1, 0xb6, 0xe6, 0xc1, 0xd6, 0x92, 0x8d, 0x8d, 0xfe, 0x9f, 0x8d, 0x60, 0xe5, 0xbe, 0xaf, - 0xef, 0x7e, 0x8e, 0x36, 0xf3, 0xb2, 0x64, 0xb5, 0xcf, 0x79, 0x59, 0x7d, 0x18, 0xe6, 0xbc, 0x3c, - 0x74, 0x21, 0x3e, 0x80, 0xb9, 0xb8, 0x09, 0x90, 0xbd, 0xa8, 0x7b, 0x7f, 0x25, 0xd5, 0xff, 0xf7, - 0x20, 0x47, 0x1b, 0xef, 0x01, 0xcc, 0xe6, 0x09, 0x3d, 0xcd, 0xa8, 0xdc, 0xdb, 0x07, 0xf5, 0x9d, - 0x15, 0x52, 0x65, 0xea, 0xe8, 0xed, 0x8f, 0xfb, 0xd7, 0x3e, 0x9f, 0x24, 0x57, 0x7b, 0x23, 0x1a, - 0xee, 0x07, 0xfe, 0xf5, 0x84, 0x47, 0x7e, 0x74, 0x1d, 0x11, 0xfe, 0x89, 0xc6, 0x37, 0xfb, 0x41, - 0xe4, 0xed, 0xcb, 0xb1, 0xdc, 0xbf, 0xb3, 0x72, 0x55, 0x92, 0xff, 0xbd, 0x7c, 0xf9, 0x77, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x30, 0x2f, 0x8a, 0x5c, 0xed, 0x0c, 0x00, 0x00, + // 2155 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x58, 0xdd, 0x72, 0xdb, 0xc6, + 0x15, 0x36, 0x28, 0x50, 0x22, 0x0f, 0x7f, 0x04, 0xad, 0x1c, 0x99, 0xa5, 0xec, 0x44, 0x41, 0x13, + 0x9b, 0xe3, 0x3a, 0x92, 0xa3, 0x76, 0x5a, 0x4f, 0xdb, 0xa4, 0x43, 0x91, 0x90, 0x09, 0x99, 0x02, + 0x98, 0x25, 0xe4, 0x9f, 0xfa, 0x62, 0x07, 0x22, 0x97, 0x22, 0x2a, 0x10, 0x60, 0x81, 0xa5, 0x3d, + 0xba, 0xec, 0xf4, 0xae, 0x2f, 0xd2, 0x5e, 0xf5, 0x09, 0xfa, 0x2e, 0xbd, 0xed, 0x13, 0x74, 0x7a, + 0xd9, 0xd9, 0xc5, 0x82, 0x04, 0x29, 0xca, 0xc9, 0x8d, 0x4d, 0x7c, 0xe7, 0xdb, 0xb3, 0xe7, 0x77, + 0xcf, 0xae, 0x60, 0x2f, 0x0a, 0x67, 0x8c, 0x46, 0xd1, 0x74, 0x70, 0x94, 0xfc, 0x3a, 0x9c, 0x46, + 0x21, 0x0b, 0x51, 0x71, 0x8e, 0xd7, 0x8b, 0xd1, 0x74, 0x90, 0xa0, 0xfa, 0xff, 0xf2, 0x80, 0xfa, + 0x34, 0x18, 0xf6, 0xdc, 0x9b, 0x09, 0x0d, 0x18, 0xa6, 0x7f, 0x9e, 0xd1, 0x98, 0x21, 0x04, 0xea, + 0x90, 0xc6, 0xac, 0xa6, 0x1c, 0x28, 0x8d, 0x32, 0x16, 0xbf, 0x91, 0x06, 0x1b, 0xee, 0x84, 0xd5, + 0x72, 0x07, 0x4a, 0x63, 0x03, 0xf3, 0x9f, 0xe8, 0x67, 0x50, 0x70, 0x27, 0x8c, 0x4c, 0x62, 0x97, + 0xd5, 0xca, 0x02, 0xde, 0x72, 0x27, 0xec, 0x3c, 0x76, 0x19, 0xfa, 0x12, 0xca, 0xd3, 0x44, 0x25, + 0x19, 0xbb, 0xf1, 0xb8, 0xb6, 0x21, 0x14, 0x95, 0x24, 0xd6, 0x71, 0xe3, 0x31, 0x6a, 0x80, 0x36, + 0xf2, 0x02, 0xd7, 0x27, 0x03, 0x9f, 0x7d, 0x20, 0x43, 0xea, 0x33, 0xb7, 0xa6, 0x1e, 0x28, 0x8d, + 0x3c, 0xae, 0x0a, 0xbc, 0xe5, 0xb3, 0x0f, 0x6d, 0x8e, 0xa2, 0x27, 0xb0, 0x9d, 0x2a, 0x8b, 0x12, + 0x03, 0x6b, 0xf9, 0x03, 0xa5, 0x51, 0xc4, 0xd5, 0xe9, 0xb2, 0xd9, 0x4f, 0x60, 0x9b, 0x79, 0x13, + 0x1a, 0xce, 0x18, 0x89, 0xe9, 0x20, 0x0c, 0x86, 0x71, 0x6d, 0x33, 0xd1, 0x28, 0xe1, 0x7e, 0x82, + 0x22, 0x1d, 0x2a, 0x23, 0x4a, 0x89, 0xef, 0x4d, 0x3c, 0x46, 0xb8, 0xf9, 0x5b, 0xc2, 0xfc, 0xd2, + 0x88, 0xd2, 0x2e, 0xc7, 0xfa, 0x2e, 0x43, 0x5f, 0x41, 0x75, 0xc1, 0x11, 0x3e, 0x56, 0x04, 0xa9, + 0x9c, 0x92, 0x84, 0xa3, 0xcf, 0x40, 0x0b, 0x67, 0xec, 0x2a, 0xf4, 0x82, 0x2b, 0x32, 0x18, 0xbb, + 0x01, 0xf1, 0x86, 0xb5, 0xc2, 0x81, 0xd2, 0x50, 0x4f, 0x72, 0xcf, 0x15, 0x5c, 0x4d, 0x65, 0xad, + 0xb1, 0x1b, 0x98, 0x43, 0xf4, 0x18, 0xb6, 0x7d, 0x37, 0x66, 0x64, 0x1c, 0x4e, 0xc9, 0x74, 0x76, + 0x79, 0x4d, 0x6f, 0x6a, 0x55, 0x11, 0x99, 0x0a, 0x87, 0x3b, 0xe1, 0xb4, 0x27, 0x40, 0xf4, 0x08, + 0x40, 0x44, 0x45, 0x6c, 0x5e, 0x2b, 0x0a, 0x1f, 0x8a, 0x1c, 0x11, 0x1b, 0xa3, 0x6f, 0xa1, 0x24, + 0xb2, 0x49, 0xc6, 0x5e, 0xc0, 0xe2, 0x1a, 0x1c, 0x6c, 0x34, 0x4a, 0xc7, 0xda, 0xa1, 0x1f, 0xf0, + 0xc4, 0x62, 0x2e, 0xe9, 0x78, 0x01, 0xc3, 0x10, 0xa5, 0x3f, 0x63, 0x34, 0x84, 0x5d, 0x9e, 0x45, + 0x32, 0x98, 0xc5, 0x2c, 0x9c, 0x90, 0x88, 0x0e, 0xc2, 0x68, 0x18, 0xd7, 0x4a, 0x62, 0xe9, 0xaf, + 0x0e, 0xe7, 0xc5, 0x71, 0x78, 0xbb, 0x1a, 0x0e, 0xdb, 0x34, 0x66, 0x2d, 0xb1, 0x0e, 0x27, 0xcb, + 0x8c, 0x80, 0x45, 0x37, 0x78, 0x67, 0xb8, 0x8a, 0xa3, 0x67, 0x80, 0x5c, 0xdf, 0x0f, 0x3f, 0x92, + 0x98, 0xfa, 0x23, 0x22, 0xb3, 0x53, 0xdb, 0x3e, 0x50, 0x1a, 0x05, 0xac, 0x09, 0x49, 0x9f, 0xfa, + 0x23, 0xa9, 0x1e, 0xfd, 0x1a, 0x2a, 0xc2, 0xa6, 0x11, 0x75, 0xd9, 0x2c, 0xa2, 0x71, 0x4d, 0x3b, + 0xd8, 0x68, 0x54, 0x8f, 0x77, 0xa4, 0x23, 0xa7, 0x09, 0x7c, 0xe2, 0x31, 0x5c, 0xe6, 0x3c, 0xf9, + 0x1d, 0xd7, 0xdb, 0xb0, 0xb7, 0xde, 0x24, 0x5e, 0xa3, 0x3c, 0xa6, 0xbc, 0x6c, 0x55, 0xcc, 0x7f, + 0xa2, 0xfb, 0x90, 0xff, 0xe0, 0xfa, 0x33, 0x2a, 0xea, 0xb6, 0x8c, 0x93, 0x8f, 0xdf, 0xe6, 0x5e, + 0x28, 0xfa, 0x0b, 0xd8, 0x75, 0x22, 0x77, 0x70, 0xbd, 0x52, 0xfa, 0xab, 0x95, 0xab, 0xdc, 0xaa, + 0x5c, 0xfd, 0x1f, 0x0a, 0x54, 0xe4, 0xaa, 0x3e, 0x73, 0xd9, 0x2c, 0x46, 0xdf, 0x40, 0x3e, 0x66, + 0x2e, 0xa3, 0x82, 0x5d, 0x3d, 0x7e, 0x90, 0x89, 0x67, 0x86, 0x48, 0x71, 0xc2, 0x42, 0x75, 0x28, + 0x4c, 0x23, 0xea, 0x4d, 0xdc, 0xab, 0xd4, 0xae, 0xf9, 0x37, 0xd2, 0x21, 0x2f, 0x16, 0x8b, 0x96, + 0x29, 0x1d, 0x97, 0xb3, 0x59, 0xc5, 0x89, 0x08, 0x35, 0x20, 0x3f, 0x66, 0xfe, 0x20, 0xae, 0xa9, + 0x22, 0x7d, 0x48, 0x72, 0x3a, 0x4e, 0xb7, 0xd5, 0x64, 0x8c, 0x4e, 0xa6, 0x0c, 0x27, 0x04, 0xfd, + 0x7b, 0xd8, 0x16, 0x2b, 0x4f, 0x29, 0xfd, 0x54, 0x6f, 0x3f, 0x00, 0xde, 0xb9, 0xa2, 0x13, 0x92, + 0xfe, 0xde, 0x74, 0x27, 0xbc, 0x09, 0xf4, 0x21, 0x68, 0x8b, 0xf5, 0xf1, 0x34, 0x0c, 0x62, 0xbe, + 0xbb, 0xc6, 0xcd, 0xe0, 0x15, 0xcf, 0x1b, 0x44, 0xb4, 0x86, 0x22, 0x56, 0x55, 0x25, 0x7e, 0x4a, + 0xa9, 0x68, 0x8e, 0xc7, 0x49, 0x3f, 0x12, 0x3f, 0x1c, 0x5c, 0xf3, 0x0e, 0x77, 0x6f, 0xa4, 0xfa, + 0x0a, 0x87, 0xbb, 0xe1, 0xe0, 0xba, 0xcd, 0x41, 0xfd, 0x7d, 0x72, 0x08, 0x39, 0x61, 0xe2, 0xe5, + 0x4f, 0xce, 0xc4, 0x22, 0x58, 0xb9, 0x3b, 0x83, 0xa5, 0xbf, 0x87, 0xdd, 0x25, 0xe5, 0xd2, 0x8b, + 0x6c, 0x0e, 0x94, 0x95, 0x1c, 0x34, 0x60, 0x6b, 0xe4, 0x7a, 0xfe, 0x2c, 0x4a, 0x15, 0x57, 0xd3, + 0x92, 0x4c, 0x50, 0x9c, 0x8a, 0xf5, 0x87, 0x50, 0xc7, 0x34, 0xa6, 0xec, 0xdc, 0x8b, 0x63, 0x2f, + 0x0c, 0x5a, 0x61, 0xc0, 0xa2, 0xd0, 0x97, 0x1e, 0xe8, 0x8f, 0x60, 0x7f, 0xad, 0x34, 0x31, 0x81, + 0x2f, 0xfe, 0x61, 0x46, 0xa3, 0x9b, 0xf5, 0x8b, 0x7f, 0x80, 0xfd, 0xb5, 0x52, 0x69, 0xff, 0x33, + 0xc8, 0x4f, 0x5d, 0x2f, 0x8a, 0x6b, 0x39, 0x51, 0x03, 0x7b, 0x4b, 0x25, 0xe7, 0x45, 0x1d, 0x2f, + 0x66, 0x61, 0x74, 0x83, 0x13, 0xd2, 0x99, 0x5a, 0x50, 0xb4, 0x9c, 0xfe, 0x37, 0x05, 0x4a, 0x19, + 0x21, 0xda, 0x87, 0x62, 0x10, 0x0e, 0x29, 0x19, 0x45, 0xe1, 0x24, 0x0d, 0x02, 0x07, 0x4e, 0xa3, + 0x70, 0xc2, 0x6b, 0x42, 0x08, 0x59, 0x28, 0x6b, 0x74, 0x93, 0x7f, 0x3a, 0x21, 0xfa, 0x06, 0xb6, + 0xc6, 0x89, 0x02, 0x71, 0x6c, 0x96, 0x8e, 0x77, 0x57, 0xf6, 0x6e, 0xbb, 0xcc, 0xc5, 0x29, 0xe7, + 0x4c, 0x2d, 0x6c, 0x68, 0xea, 0x99, 0x5a, 0x50, 0xb5, 0xfc, 0x99, 0x5a, 0xc8, 0x6b, 0x9b, 0x67, + 0x6a, 0x61, 0x53, 0xdb, 0xd2, 0xff, 0xa3, 0x40, 0x21, 0x65, 0x73, 0x4b, 0x78, 0x48, 0x09, 0xaf, + 0x0b, 0x59, 0x4c, 0x05, 0x0e, 0x38, 0xde, 0x84, 0xa2, 0x03, 0x28, 0x0b, 0xe1, 0x72, 0x89, 0x02, + 0xc7, 0x9a, 0xa2, 0x4c, 0xc5, 0x79, 0x9e, 0x32, 0x44, 0x3d, 0xaa, 0xf2, 0x3c, 0x4f, 0x28, 0xe9, + 0x48, 0x8a, 0x67, 0x83, 0x01, 0x8d, 0xe3, 0x64, 0x97, 0x7c, 0x42, 0x91, 0x98, 0xd8, 0xe8, 0x31, + 0x6c, 0xa7, 0x94, 0x74, 0xaf, 0xcd, 0xa4, 0x5e, 0x25, 0x2c, 0xb7, 0x6b, 0x80, 0x96, 0xe5, 0x4d, + 0x16, 0x13, 0xa4, 0xba, 0x20, 0xf2, 0x4d, 0x13, 0xe7, 0xf5, 0x3f, 0xc1, 0x03, 0x91, 0xca, 0x5e, + 0x14, 0x5e, 0xba, 0x97, 0x9e, 0xef, 0xb1, 0x9b, 0xb4, 0xc8, 0xb9, 0xe3, 0x51, 0x38, 0x21, 0x3c, + 0xb6, 0x69, 0x0a, 0x38, 0x60, 0x85, 0x43, 0xca, 0x53, 0xc0, 0xc2, 0x44, 0x24, 0x53, 0xc0, 0x42, + 0x21, 0xc8, 0x4e, 0xde, 0x8d, 0xa5, 0xc9, 0xab, 0x5f, 0x43, 0xed, 0xf6, 0x5e, 0xb2, 0x66, 0x0e, + 0xa0, 0x34, 0x5d, 0xc0, 0x62, 0x3b, 0x05, 0x67, 0xa1, 0x6c, 0x6e, 0x73, 0x3f, 0x9e, 0x5b, 0xfd, + 0xef, 0x0a, 0xec, 0x9c, 0xcc, 0x3c, 0x7f, 0xb8, 0xd4, 0xb8, 0x59, 0xeb, 0x94, 0xe5, 0x7b, 0xc1, + 0xba, 0xa1, 0x9f, 0x5b, 0x3b, 0xf4, 0xd7, 0x0d, 0xd6, 0x8d, 0x3b, 0x07, 0xeb, 0x17, 0x50, 0x5a, + 0xcc, 0xd4, 0xe4, 0x5c, 0x2c, 0x63, 0x18, 0xa7, 0x03, 0x35, 0xd6, 0x5f, 0x00, 0xca, 0x1a, 0x2a, + 0x03, 0x32, 0x3f, 0x3f, 0x94, 0xbb, 0xcf, 0x8f, 0x87, 0x50, 0xef, 0xcf, 0x2e, 0xe3, 0x41, 0xe4, + 0x5d, 0xd2, 0x0e, 0xf3, 0x07, 0xc6, 0x07, 0x1a, 0xb0, 0x38, 0xed, 0xd2, 0xff, 0xaa, 0x50, 0x9c, + 0xa3, 0xe8, 0x10, 0x76, 0xbd, 0x60, 0x10, 0x4e, 0x52, 0xa3, 0x03, 0xea, 0x73, 0xbb, 0x93, 0x79, + 0xb4, 0x93, 0x8a, 0x5a, 0x89, 0xc4, 0x1c, 0x72, 0xfe, 0x92, 0x93, 0x92, 0x9f, 0x4b, 0xf8, 0x59, + 0x1f, 0x13, 0x7e, 0x03, 0xb4, 0xb9, 0x7e, 0x7e, 0xc0, 0xcf, 0x83, 0x82, 0xab, 0x29, 0xce, 0x8d, + 0x49, 0x98, 0x73, 0xcd, 0x29, 0x53, 0x4d, 0x98, 0x29, 0x2e, 0x99, 0x5f, 0x42, 0x99, 0xf7, 0x43, + 0xcc, 0xdc, 0xc9, 0x94, 0x04, 0xb1, 0xe8, 0x0b, 0x15, 0x97, 0xe6, 0x98, 0x15, 0xa3, 0xef, 0x00, + 0x28, 0xf7, 0x8f, 0xb0, 0x9b, 0x29, 0x15, 0x2d, 0x51, 0x3d, 0xfe, 0x3c, 0x53, 0x18, 0xf3, 0x00, + 0x1c, 0x8a, 0x7f, 0x9d, 0x9b, 0x29, 0xc5, 0x45, 0x9a, 0xfe, 0x44, 0xdf, 0x43, 0x65, 0x14, 0x46, + 0x1f, 0xdd, 0x68, 0x48, 0x04, 0x28, 0x8f, 0x8d, 0xec, 0x94, 0x3c, 0x4d, 0xe4, 0x62, 0x79, 0xe7, + 0x1e, 0x2e, 0x8f, 0x32, 0xdf, 0xe8, 0x15, 0xa0, 0x74, 0xbd, 0xe8, 0xf2, 0x44, 0x49, 0x41, 0x28, + 0xd9, 0xbf, 0xad, 0x84, 0x1f, 0xd2, 0xa9, 0x22, 0x6d, 0xb4, 0x82, 0xa1, 0xdf, 0x41, 0x39, 0xa6, + 0x8c, 0xf9, 0x54, 0xaa, 0x29, 0x0a, 0x35, 0x7b, 0x4b, 0x37, 0x20, 0x2e, 0x4e, 0x35, 0x94, 0xe2, + 0xc5, 0x27, 0x3a, 0x81, 0x6d, 0xdf, 0x0b, 0xae, 0xb3, 0x66, 0x80, 0x58, 0x5f, 0xcb, 0xac, 0xef, + 0x7a, 0xc1, 0x75, 0xd6, 0x86, 0x8a, 0x9f, 0x05, 0xf4, 0xdf, 0x43, 0x71, 0x1e, 0x25, 0x54, 0x82, + 0xad, 0x0b, 0xeb, 0x95, 0x65, 0xbf, 0xb1, 0xb4, 0x7b, 0xa8, 0x00, 0x6a, 0xdf, 0xb0, 0xda, 0x9a, + 0xc2, 0x61, 0x6c, 0xb4, 0x0c, 0xf3, 0xb5, 0xa1, 0xe5, 0xf8, 0xc7, 0xa9, 0x8d, 0xdf, 0x34, 0x71, + 0x5b, 0xdb, 0x38, 0xd9, 0x82, 0xbc, 0xd8, 0x57, 0xff, 0x97, 0x02, 0x05, 0x91, 0xc1, 0x60, 0x14, + 0xa2, 0x5f, 0xc0, 0xbc, 0xb8, 0xc4, 0xe1, 0xc6, 0x07, 0xae, 0xa8, 0xba, 0x0a, 0x9e, 0x17, 0x8c, + 0x23, 0x71, 0x4e, 0x9e, 0x97, 0xc6, 0x9c, 0x9c, 0x4b, 0xc8, 0xa9, 0x60, 0x4e, 0x7e, 0x9a, 0xd1, + 0xbc, 0x74, 0xe4, 0xa8, 0x78, 0x3b, 0x15, 0xa4, 0x27, 0xec, 0xd3, 0x8c, 0xe2, 0xa5, 0x93, 0x58, + 0xc5, 0xdb, 0xa9, 0x40, 0x72, 0xf5, 0xdf, 0x40, 0x39, 0x9b, 0x73, 0xf4, 0x04, 0x54, 0x2f, 0x18, + 0x85, 0xb2, 0x11, 0x77, 0x57, 0x8a, 0x8b, 0x3b, 0x89, 0x05, 0x41, 0x47, 0xa0, 0xad, 0xe6, 0x59, + 0xaf, 0x40, 0x29, 0x93, 0x34, 0xfd, 0xdf, 0x0a, 0x54, 0x96, 0x92, 0xf0, 0x93, 0xb5, 0xa3, 0xef, + 0xa0, 0xfc, 0xd1, 0x8b, 0x28, 0xc9, 0x8e, 0xff, 0xea, 0x71, 0x7d, 0x79, 0xfc, 0xa7, 0xff, 0xb7, + 0xc2, 0x21, 0xc5, 0x25, 0xce, 0x97, 0x00, 0xfa, 0x03, 0x54, 0xe5, 0x4a, 0x32, 0xa4, 0xcc, 0xf5, + 0x7c, 0x11, 0xaa, 0xea, 0x52, 0x79, 0x48, 0x6e, 0x5b, 0xc8, 0x71, 0x65, 0x94, 0xfd, 0x44, 0x5f, + 0x2f, 0x14, 0xc4, 0x2c, 0xf2, 0x82, 0x2b, 0x11, 0xbf, 0xe2, 0x9c, 0xd6, 0x17, 0xe0, 0xd3, 0x7f, + 0x2a, 0x50, 0xce, 0x5e, 0x2c, 0x51, 0x05, 0x8a, 0xa6, 0x45, 0x4e, 0xbb, 0xe6, 0xcb, 0x8e, 0xa3, + 0xdd, 0xe3, 0x9f, 0xfd, 0x8b, 0x56, 0xcb, 0x30, 0xda, 0x06, 0x2f, 0x27, 0x04, 0xd5, 0xd3, 0xa6, + 0xd9, 0x35, 0xda, 0xc4, 0x31, 0xcf, 0x0d, 0xfb, 0xc2, 0xd1, 0x72, 0x68, 0x17, 0xb6, 0x25, 0x66, + 0xd9, 0x04, 0xdb, 0x17, 0x8e, 0xa1, 0x6d, 0x20, 0x0d, 0xca, 0x12, 0x34, 0x30, 0xb6, 0xb1, 0xa6, + 0xa2, 0xaf, 0xe0, 0x40, 0x22, 0xa6, 0xd5, 0xb2, 0x31, 0x36, 0x5a, 0x0e, 0xe9, 0x35, 0xdf, 0x9d, + 0x1b, 0x96, 0x43, 0xda, 0x86, 0xd3, 0x34, 0xbb, 0x7d, 0x2d, 0x8f, 0xbe, 0x80, 0xfd, 0x39, 0xab, + 0x7f, 0x71, 0x7a, 0x6a, 0xb6, 0x4c, 0x4e, 0x38, 0x69, 0x76, 0x9b, 0x56, 0xcb, 0xd0, 0x36, 0x9f, + 0xfe, 0x45, 0x85, 0xca, 0x92, 0xe3, 0xcb, 0x95, 0x5f, 0x81, 0xa2, 0x65, 0x4b, 0x7d, 0x9a, 0xc2, + 0xcd, 0xb0, 0x2d, 0xd3, 0xb6, 0x48, 0xdb, 0x68, 0xd9, 0x6d, 0xde, 0x03, 0x9f, 0xc1, 0x4e, 0xd7, + 0xb4, 0x5e, 0x11, 0xcb, 0x76, 0x88, 0xd1, 0x35, 0x5f, 0x9a, 0x27, 0x5d, 0x6e, 0xef, 0x7d, 0xd0, + 0x6c, 0x8b, 0xb4, 0x3a, 0x4d, 0xd3, 0x9a, 0xbb, 0xa6, 0x72, 0x94, 0x5f, 0x85, 0x89, 0xf1, 0x96, + 0x47, 0xa0, 0x4f, 0xce, 0x9b, 0x6f, 0xb5, 0x3c, 0xaa, 0xc1, 0xfd, 0xf5, 0xc6, 0xa1, 0x3d, 0x40, + 0xdc, 0xb9, 0xf3, 0x5e, 0xd7, 0x70, 0x0c, 0x92, 0xf6, 0xda, 0x16, 0x0f, 0x91, 0xd0, 0xd3, 0x6c, + 0xb7, 0x49, 0xe2, 0x9e, 0x56, 0xe0, 0x96, 0x48, 0x46, 0x9f, 0xb4, 0xcd, 0x7e, 0xf3, 0x84, 0xc3, + 0x45, 0xbe, 0xa7, 0x69, 0xbd, 0xb6, 0xcd, 0x96, 0x41, 0x5a, 0x5c, 0x2d, 0x47, 0x81, 0x93, 0x53, + 0xf4, 0xc2, 0x6a, 0x1b, 0xb8, 0xd7, 0x34, 0xdb, 0x5a, 0x09, 0xed, 0xc3, 0x83, 0x14, 0x36, 0xde, + 0xf6, 0x4c, 0xfc, 0x8e, 0x38, 0xb6, 0x4d, 0xfa, 0xb6, 0x6d, 0x69, 0xe5, 0xac, 0x26, 0xee, 0xad, + 0xdd, 0x33, 0x2c, 0xad, 0x82, 0x1e, 0xc0, 0xee, 0x79, 0xaf, 0x47, 0x52, 0x49, 0xea, 0x6c, 0x95, + 0xd3, 0x9b, 0xed, 0x36, 0x36, 0xfa, 0x7d, 0x72, 0x6e, 0xf6, 0xcf, 0x9b, 0x4e, 0xab, 0xa3, 0x6d, + 0x73, 0x97, 0xfa, 0x86, 0x43, 0x1c, 0xdb, 0x69, 0x76, 0x17, 0xb8, 0xc6, 0x0d, 0x5a, 0xe0, 0x7c, + 0xd3, 0xae, 0xfd, 0x46, 0xdb, 0xe1, 0x01, 0xe7, 0xb0, 0xfd, 0x5a, 0x9a, 0x88, 0xb8, 0xef, 0x32, + 0x3d, 0xe9, 0x9e, 0xda, 0x2e, 0x07, 0x4d, 0xeb, 0x75, 0xb3, 0x6b, 0xb6, 0xc9, 0x2b, 0xe3, 0x9d, + 0x38, 0xab, 0xee, 0x73, 0x30, 0xb1, 0x8c, 0xf4, 0xb0, 0xfd, 0x92, 0x1b, 0xa2, 0x7d, 0xc6, 0x2b, + 0xae, 0x65, 0xe2, 0xd6, 0x45, 0xb7, 0x89, 0x65, 0x71, 0xed, 0x1d, 0xff, 0x75, 0x13, 0x36, 0xc5, + 0x64, 0x8d, 0x50, 0x87, 0x37, 0xec, 0xfc, 0x9d, 0x89, 0x1e, 0x7d, 0xf2, 0xfd, 0x59, 0xaf, 0xad, + 0x7f, 0x4e, 0xcd, 0xe2, 0xe7, 0x0a, 0x3a, 0x83, 0x72, 0xf6, 0x15, 0x87, 0xb2, 0x63, 0x69, 0xcd, + 0xf3, 0xee, 0x93, 0xba, 0x5e, 0x81, 0x66, 0xc4, 0xcc, 0x9b, 0xf0, 0x97, 0x9a, 0x7c, 0xf4, 0xa0, + 0x7a, 0x86, 0xbf, 0xf2, 0x92, 0xaa, 0xef, 0xaf, 0x95, 0xc9, 0xab, 0x45, 0x37, 0x71, 0x51, 0x3e, + 0x3b, 0x6e, 0xb9, 0xb8, 0xfc, 0xd6, 0xa9, 0x7f, 0x7e, 0x97, 0x58, 0x6a, 0x1b, 0xc2, 0xee, 0x9a, + 0x97, 0x04, 0xfa, 0x3a, 0x6b, 0xc1, 0x9d, 0xef, 0x90, 0xfa, 0xe3, 0x1f, 0xa3, 0x2d, 0x76, 0x59, + 0xf3, 0xe4, 0x58, 0xda, 0xe5, 0xee, 0x07, 0xcb, 0xd2, 0x2e, 0x9f, 0x7a, 0xb9, 0xbc, 0x07, 0x6d, + 0xf5, 0x86, 0x8a, 0xf4, 0xd5, 0xb5, 0xb7, 0xaf, 0xca, 0xf5, 0x9f, 0x7f, 0x92, 0x23, 0x95, 0x9b, + 0x00, 0x8b, 0x7b, 0x1e, 0x7a, 0x98, 0x59, 0x72, 0xeb, 0x9e, 0x5a, 0x7f, 0x74, 0x87, 0x54, 0xaa, + 0x72, 0x60, 0x77, 0xcd, 0xc5, 0x6f, 0x29, 0x1a, 0x77, 0x5f, 0x0c, 0xeb, 0xf7, 0xd7, 0xdd, 0x8f, + 0x9e, 0x2b, 0x27, 0xdf, 0xfe, 0xf1, 0xe8, 0xca, 0x63, 0xe3, 0xd9, 0xe5, 0xe1, 0x20, 0x9c, 0x1c, + 0xf9, 0xde, 0xd5, 0x98, 0x05, 0x5e, 0x70, 0x15, 0x50, 0xf6, 0x31, 0x8c, 0xae, 0x8f, 0xfc, 0x60, + 0x78, 0x24, 0x86, 0xcd, 0xd1, 0x7c, 0xf9, 0xe5, 0xa6, 0xf8, 0x5b, 0xdd, 0x2f, 0xff, 0x1f, 0x00, + 0x00, 0xff, 0xff, 0xe9, 0x0c, 0xc3, 0x27, 0xdb, 0x13, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1281,6 +1908,10 @@ type RouterClient interface { //keys. It retrieves the relevant channel policies from the graph in order to //calculate the correct fees and time locks. BuildRoute(ctx context.Context, in *BuildRouteRequest, opts ...grpc.CallOption) (*BuildRouteResponse, error) + //* + //SubscribeHtlcEvents creates a uni-directional stream from the server to + //the client which delivers a stream of htlc events. + SubscribeHtlcEvents(ctx context.Context, in *SubscribeHtlcEventsRequest, opts ...grpc.CallOption) (Router_SubscribeHtlcEventsClient, error) } type routerClient struct { @@ -1409,6 +2040,38 @@ func (c *routerClient) BuildRoute(ctx context.Context, in *BuildRouteRequest, op return out, nil } +func (c *routerClient) SubscribeHtlcEvents(ctx context.Context, in *SubscribeHtlcEventsRequest, opts ...grpc.CallOption) (Router_SubscribeHtlcEventsClient, error) { + stream, err := c.cc.NewStream(ctx, &_Router_serviceDesc.Streams[2], "/routerrpc.Router/SubscribeHtlcEvents", opts...) + if err != nil { + return nil, err + } + x := &routerSubscribeHtlcEventsClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type Router_SubscribeHtlcEventsClient interface { + Recv() (*HtlcEvent, error) + grpc.ClientStream +} + +type routerSubscribeHtlcEventsClient struct { + grpc.ClientStream +} + +func (x *routerSubscribeHtlcEventsClient) Recv() (*HtlcEvent, error) { + m := new(HtlcEvent) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + // RouterServer is the server API for Router service. type RouterServer interface { //* @@ -1446,6 +2109,10 @@ type RouterServer interface { //keys. It retrieves the relevant channel policies from the graph in order to //calculate the correct fees and time locks. BuildRoute(context.Context, *BuildRouteRequest) (*BuildRouteResponse, error) + //* + //SubscribeHtlcEvents creates a uni-directional stream from the server to + //the client which delivers a stream of htlc events. + SubscribeHtlcEvents(*SubscribeHtlcEventsRequest, Router_SubscribeHtlcEventsServer) error } func RegisterRouterServer(s *grpc.Server, srv RouterServer) { @@ -1602,6 +2269,27 @@ func _Router_BuildRoute_Handler(srv interface{}, ctx context.Context, dec func(i return interceptor(ctx, in, info, handler) } +func _Router_SubscribeHtlcEvents_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(SubscribeHtlcEventsRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(RouterServer).SubscribeHtlcEvents(m, &routerSubscribeHtlcEventsServer{stream}) +} + +type Router_SubscribeHtlcEventsServer interface { + Send(*HtlcEvent) error + grpc.ServerStream +} + +type routerSubscribeHtlcEventsServer struct { + grpc.ServerStream +} + +func (x *routerSubscribeHtlcEventsServer) Send(m *HtlcEvent) error { + return x.ServerStream.SendMsg(m) +} + var _Router_serviceDesc = grpc.ServiceDesc{ ServiceName: "routerrpc.Router", HandlerType: (*RouterServer)(nil), @@ -1642,6 +2330,11 @@ var _Router_serviceDesc = grpc.ServiceDesc{ Handler: _Router_TrackPayment_Handler, ServerStreams: true, }, + { + StreamName: "SubscribeHtlcEvents", + Handler: _Router_SubscribeHtlcEvents_Handler, + ServerStreams: true, + }, }, Metadata: "routerrpc/router.proto", } diff --git a/lnrpc/routerrpc/router.proto b/lnrpc/routerrpc/router.proto index d5e53ff9..027b6c51 100644 --- a/lnrpc/routerrpc/router.proto +++ b/lnrpc/routerrpc/router.proto @@ -333,6 +333,135 @@ message BuildRouteResponse { lnrpc.Route route = 1; } + +message SubscribeHtlcEventsRequest{} + +/** +HtlcEvent contains the htlc event that was processed. These are served on a +best-effort basis; events are not persisted, delivery is not guaranteed +(in the event of a crash in the switch, forward events may be lost) and +some events may be replayed upon restart. Events consumed from this package +should be de-duplicated by the htlc's unique combination of incoming and +outgoing channel id and htlc id. [EXPERIMENTAL] +*/ +message HtlcEvent{ + /** + The short channel id that the incoming htlc arrived at our node on. This + value is zero for sends. + */ + uint64 incoming_channel_id = 1; + + /** + The short channel id that the outgoing htlc left our node on. This value + is zero for receives. + */ + uint64 outgoing_channel_id = 2; + + /** + Incoming id is the index of the incoming htlc in the incoming channel. + This value is zero for sends. + */ + uint64 incoming_htlc_id = 3; + + /** + Outgoing id is the index of the outgoing htlc in the outgoing channel. + This value is zero for receives. + */ + uint64 outgoing_htlc_id = 4; + + /** + The time in unix nanoseconds that the event occurred. + */ + uint64 timestamp_ns = 5; + + enum EventType{ + UNKNOWN = 0; + SEND = 1; + RECEIVE = 2; + FORWARD = 3; + } + + /** + The event type indicates whether the htlc was part of a send, receive or + forward. + */ + EventType event_type = 6; + + oneof event { + ForwardEvent forward_event = 7; + ForwardFailEvent forward_fail_event = 8; + SettleEvent settle_event = 9; + LinkFailEvent link_fail_event = 10; + } +} + +message HtlcInfo{ + // The timelock on the incoming htlc. + uint32 incoming_timelock = 1; + + // The timelock on the outgoing htlc. + uint32 outgoing_timelock = 2; + + // The amount of the incoming htlc. + uint64 incoming_amt_msat = 3; + + // The amount of the outgoing htlc. + uint64 outgoing_amt_msat = 4; +} + +message ForwardEvent{ + // Info contains details about the htlc that was forwarded. + HtlcInfo info = 1; +} + +message ForwardFailEvent{} + +message SettleEvent{} + +message LinkFailEvent{ + // Info contains details about the htlc that we failed. + HtlcInfo info = 1; + + // FailureCode is the BOLT error code for the failure. + lnrpc.Failure.FailureCode wire_failure = 2; + + /** + FailureDetail provides additional information about the reason for the + failure. This detail enriches the information provided by the wire message + and may be 'no detail' if the wire message requires no additional metadata. + */ + FailureDetail failure_detail = 3; + + // A string representation of the link failure. + string failure_string = 4; +} + +enum FailureDetail { + UNKNOWN = 0; + NO_DETAIL = 1; + ONION_DECODE = 2; + LINK_NOT_ELIGIBLE = 3; + ON_CHAIN_TIMEOUT = 4; + HTLC_EXCEEDS_MAX = 5; + INSUFFICIENT_BALANCE =6; + INCOMPLETE_FORWARD = 7; + HTLC_ADD_FAILED = 8; + FORWARDS_DISABLED = 9; + INVOICE_CANCELED = 10; + INVOICE_UNDERPAID = 11; + INVOICE_EXPIRY_TOO_SOON = 12; + INVOICE_NOT_OPEN = 13; + MPP_INVOICE_TIMEOUT = 14; + ADDRESS_MISMATCH = 15; + SET_TOTAL_MISMATCH = 16; + SET_TOTAL_TOO_LOW = 17; + SET_OVERPAID = 18; + UNKNOWN_INVOICE = 19; + INVALID_KEYSEND = 20; + MPP_IN_PROGRESS = 21; + CIRCULAR_ROUTE = 22; +} + service Router { /** SendPayment attempts to route a payment described by the passed @@ -387,4 +516,10 @@ service Router { calculate the correct fees and time locks. */ rpc BuildRoute (BuildRouteRequest) returns (BuildRouteResponse); + + /** + SubscribeHtlcEvents creates a uni-directional stream from the server to + the client which delivers a stream of htlc events. + */ + rpc SubscribeHtlcEvents (SubscribeHtlcEventsRequest) returns (stream HtlcEvent); } diff --git a/lnrpc/routerrpc/router_server.go b/lnrpc/routerrpc/router_server.go index 8bbdb387..17434699 100644 --- a/lnrpc/routerrpc/router_server.go +++ b/lnrpc/routerrpc/router_server.go @@ -82,6 +82,10 @@ var ( Entity: "offchain", Action: "read", }}, + "/routerrpc.Router/SubscribeHtlcEvents": {{ + Entity: "offchain", + Action: "read", + }}, } // DefaultRouterMacFilename is the default name of the router macaroon @@ -613,3 +617,42 @@ func (s *Server) BuildRoute(ctx context.Context, return routeResp, nil } + +// SubscribeHtlcEvents creates a uni-directional stream from the server to +// the client which delivers a stream of htlc events. +func (s *Server) SubscribeHtlcEvents(req *SubscribeHtlcEventsRequest, + stream Router_SubscribeHtlcEventsServer) error { + + htlcClient, err := s.cfg.RouterBackend.SubscribeHtlcEvents() + if err != nil { + return err + } + defer htlcClient.Cancel() + + for { + select { + case event := <-htlcClient.Updates(): + rpcEvent, err := rpcHtlcEvent(event) + if err != nil { + return err + } + + if err := stream.Send(rpcEvent); err != nil { + return err + } + + // If the stream's context is cancelled, return an error. + case <-stream.Context().Done(): + log.Debugf("htlc event stream cancelled") + return stream.Context().Err() + + // If the subscribe client terminates, exit with an error. + case <-htlcClient.Quit(): + return errors.New("htlc event subscription terminated") + + // If the server has been signalled to shut down, exit. + case <-s.quit: + return errServerShuttingDown + } + } +} diff --git a/lnrpc/routerrpc/subscribe_events.go b/lnrpc/routerrpc/subscribe_events.go new file mode 100644 index 00000000..ce65a6c8 --- /dev/null +++ b/lnrpc/routerrpc/subscribe_events.go @@ -0,0 +1,241 @@ +// +build routerrpc + +package routerrpc + +import ( + "fmt" + "time" + + "github.com/lightningnetwork/lnd/htlcswitch" + "github.com/lightningnetwork/lnd/invoices" + "github.com/lightningnetwork/lnd/lnrpc" +) + +// rpcHtlcEvent returns a rpc htlc event from a htlcswitch event. +func rpcHtlcEvent(htlcEvent interface{}) (*HtlcEvent, error) { + var ( + key htlcswitch.HtlcKey + timestamp time.Time + eventType htlcswitch.HtlcEventType + event isHtlcEvent_Event + ) + + switch e := htlcEvent.(type) { + case *htlcswitch.ForwardingEvent: + event = &HtlcEvent_ForwardEvent{ + ForwardEvent: &ForwardEvent{ + Info: rpcInfo(e.HtlcInfo), + }, + } + + key = e.HtlcKey + eventType = e.HtlcEventType + timestamp = e.Timestamp + + case *htlcswitch.ForwardingFailEvent: + event = &HtlcEvent_ForwardFailEvent{ + ForwardFailEvent: &ForwardFailEvent{}, + } + + key = e.HtlcKey + eventType = e.HtlcEventType + timestamp = e.Timestamp + + case *htlcswitch.LinkFailEvent: + failureCode, failReason, err := rpcFailReason( + e.LinkError, + ) + if err != nil { + return nil, err + } + + event = &HtlcEvent_LinkFailEvent{ + LinkFailEvent: &LinkFailEvent{ + Info: rpcInfo(e.HtlcInfo), + WireFailure: failureCode, + FailureDetail: failReason, + FailureString: e.LinkError.Error(), + }, + } + + key = e.HtlcKey + eventType = e.HtlcEventType + timestamp = e.Timestamp + + case *htlcswitch.SettleEvent: + event = &HtlcEvent_SettleEvent{ + SettleEvent: &SettleEvent{}, + } + + key = e.HtlcKey + eventType = e.HtlcEventType + timestamp = e.Timestamp + + default: + return nil, fmt.Errorf("unknown event type: %T", e) + } + + rpcEvent := &HtlcEvent{ + IncomingChannelId: key.IncomingCircuit.ChanID.ToUint64(), + OutgoingChannelId: key.OutgoingCircuit.ChanID.ToUint64(), + IncomingHtlcId: key.IncomingCircuit.HtlcID, + OutgoingHtlcId: key.OutgoingCircuit.HtlcID, + TimestampNs: uint64(timestamp.UnixNano()), + Event: event, + } + + // Convert the htlc event type to a rpc event. + switch eventType { + case htlcswitch.HtlcEventTypeSend: + rpcEvent.EventType = HtlcEvent_SEND + + case htlcswitch.HtlcEventTypeReceive: + rpcEvent.EventType = HtlcEvent_RECEIVE + + case htlcswitch.HtlcEventTypeForward: + rpcEvent.EventType = HtlcEvent_FORWARD + + default: + return nil, fmt.Errorf("unknown event type: %v", eventType) + } + + return rpcEvent, nil +} + +// rpcInfo returns a rpc struct containing the htlc information from the +// switch's htlc info struct. +func rpcInfo(info htlcswitch.HtlcInfo) *HtlcInfo { + return &HtlcInfo{ + IncomingTimelock: info.IncomingTimeLock, + OutgoingTimelock: info.OutgoingTimeLock, + IncomingAmtMsat: uint64(info.IncomingAmt), + OutgoingAmtMsat: uint64(info.OutgoingAmt), + } +} + +// rpcFailReason maps a lnwire failure message and failure detail to a rpc +// failure code and detail. +func rpcFailReason(linkErr *htlcswitch.LinkError) (lnrpc.Failure_FailureCode, + FailureDetail, error) { + + wireErr, err := marshallError(linkErr) + if err != nil { + return 0, 0, err + } + + switch failureDetail := linkErr.FailureDetail.(type) { + case invoices.FailResolutionResult: + fd, err := rpcFailureResolution(failureDetail) + return wireErr.GetCode(), fd, err + + case htlcswitch.OutgoingFailure: + fd, err := rpcOutgoingFailure(failureDetail) + return wireErr.GetCode(), fd, err + + default: + return 0, 0, fmt.Errorf("unknown failure "+ + "detail type: %T", linkErr.FailureDetail) + + } + +} + +// rpcFailureResolution maps an invoice failure resolution to a rpc failure +// detail. Invoice failures have no zero resolution results (every failure +// is accompanied with a result), so we error if we fail to match the result +// type. +func rpcFailureResolution(invoiceFailure invoices.FailResolutionResult) ( + FailureDetail, error) { + + switch invoiceFailure { + case invoices.ResultReplayToCanceled: + return FailureDetail_INVOICE_CANCELED, nil + + case invoices.ResultInvoiceAlreadyCanceled: + return FailureDetail_INVOICE_CANCELED, nil + + case invoices.ResultAmountTooLow: + return FailureDetail_INVOICE_UNDERPAID, nil + + case invoices.ResultExpiryTooSoon: + return FailureDetail_INVOICE_EXPIRY_TOO_SOON, nil + + case invoices.ResultCanceled: + return FailureDetail_INVOICE_CANCELED, nil + + case invoices.ResultInvoiceNotOpen: + return FailureDetail_INVOICE_NOT_OPEN, nil + + case invoices.ResultMppTimeout: + return FailureDetail_MPP_INVOICE_TIMEOUT, nil + + case invoices.ResultAddressMismatch: + return FailureDetail_ADDRESS_MISMATCH, nil + + case invoices.ResultHtlcSetTotalMismatch: + return FailureDetail_SET_TOTAL_MISMATCH, nil + + case invoices.ResultHtlcSetTotalTooLow: + return FailureDetail_SET_TOTAL_TOO_LOW, nil + + case invoices.ResultHtlcSetOverpayment: + return FailureDetail_SET_OVERPAID, nil + + case invoices.ResultInvoiceNotFound: + return FailureDetail_UNKNOWN_INVOICE, nil + + case invoices.ResultKeySendError: + return FailureDetail_INVALID_KEYSEND, nil + + case invoices.ResultMppInProgress: + return FailureDetail_MPP_IN_PROGRESS, nil + + default: + return 0, fmt.Errorf("unknown fail resolution: %v", + invoiceFailure.FailureString()) + } +} + +// rpcOutgoingFailure maps an outgoing failure to a rpc FailureDetail. If the +// failure detail is FailureDetailNone, which indicates that the failure was +// a wire message which required no further failure detail, we return a no +// detail failure detail to indicate that there was no additional information. +func rpcOutgoingFailure(failureDetail htlcswitch.OutgoingFailure) ( + FailureDetail, error) { + + switch failureDetail { + case htlcswitch.OutgoingFailureNone: + return FailureDetail_NO_DETAIL, nil + + case htlcswitch.OutgoingFailureDecodeError: + return FailureDetail_ONION_DECODE, nil + + case htlcswitch.OutgoingFailureLinkNotEligible: + return FailureDetail_LINK_NOT_ELIGIBLE, nil + + case htlcswitch.OutgoingFailureOnChainTimeout: + return FailureDetail_ON_CHAIN_TIMEOUT, nil + + case htlcswitch.OutgoingFailureHTLCExceedsMax: + return FailureDetail_HTLC_EXCEEDS_MAX, nil + + case htlcswitch.OutgoingFailureInsufficientBalance: + return FailureDetail_INSUFFICIENT_BALANCE, nil + + case htlcswitch.OutgoingFailureCircularRoute: + return FailureDetail_CIRCULAR_ROUTE, nil + + case htlcswitch.OutgoingFailureIncompleteForward: + return FailureDetail_INCOMPLETE_FORWARD, nil + + case htlcswitch.OutgoingFailureDownstreamHtlcAdd: + return FailureDetail_HTLC_ADD_FAILED, nil + + case htlcswitch.OutgoingFailureForwardsDisabled: + return FailureDetail_FORWARDS_DISABLED, nil + + default: + return 0, fmt.Errorf("unknown outgoing failure "+ + "detail: %v", failureDetail.FailureString()) + } +}