Add checkChannels grpc function

This commit is contained in:
Yaacov Akiba Slama
2020-12-24 18:01:57 +02:00
parent aa0db5402c
commit 11dc17ae2d
5 changed files with 498 additions and 38 deletions

View File

@@ -82,6 +82,48 @@ func sendEmail(to, cc, from, content, subject string) error {
return nil
}
func sendChannelMismatchNotification(nodeID string, notFakeChannels, closedChannels map[string]uint64) error {
var html bytes.Buffer
tpl := `
<h2>NodeID: {{ .NodeID }}</h2>
{{ if .NotFakeChannels }}<h3>Channels not fake anynmore</h3><table>
<tr><th>Channel Point</th><th>Height Hint</th></tr>
{{ range $key, $value := .NotFakeChannels }}<tr><td>{{ $key }}</td><td>{{ $value }}</td></tr>{{ end }}
</table>{{ end }}
{{ if .ClosedChannels }}<h3>Closed Channels</h3><table>
<tr><th>Channel Point</th><th>Height Hint</th></tr>
{{ range $key, $value := .ClosedChannels }}<tr><td>{{ $key }}</td><td>{{ $value }}</td></tr>{{ end }}
</table>{{ end }}
`
t, err := template.New("ChannelMismatchEmail").Parse(tpl)
if err != nil {
return err
}
if err := t.Execute(&html, struct {
NodeID string
NotFakeChannels map[string]uint64
ClosedChannels map[string]uint64
}{nodeID, notFakeChannels, closedChannels}); err != nil {
return err
}
err = sendEmail(
os.Getenv("CHANNELMISMATCH_NOTIFICATION_TO"),
os.Getenv("CHANNELMISMATCH_NOTIFICATION_CC"),
os.Getenv("CHANNELMISMATCH_NOTIFICATION_FROM"),
html.String(),
"Channel(s) Mismatch",
)
if err != nil {
log.Printf("Error sending open channel email: %v", err)
return err
}
return nil
}
func sendOpenChannelEmailNotification(
paymentHash []byte, incomingAmountMsat int64,
destination []byte, capacity int64,

View File

@@ -426,6 +426,202 @@ func (m *PaymentInformation) GetOutgoingAmountMsat() int64 {
return 0
}
type Encrypted struct {
Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Encrypted) Reset() { *m = Encrypted{} }
func (m *Encrypted) String() string { return proto.CompactTextString(m) }
func (*Encrypted) ProtoMessage() {}
func (*Encrypted) Descriptor() ([]byte, []int) {
return fileDescriptor_c69a0f5a734bca26, []int{7}
}
func (m *Encrypted) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Encrypted.Unmarshal(m, b)
}
func (m *Encrypted) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Encrypted.Marshal(b, m, deterministic)
}
func (m *Encrypted) XXX_Merge(src proto.Message) {
xxx_messageInfo_Encrypted.Merge(m, src)
}
func (m *Encrypted) XXX_Size() int {
return xxx_messageInfo_Encrypted.Size(m)
}
func (m *Encrypted) XXX_DiscardUnknown() {
xxx_messageInfo_Encrypted.DiscardUnknown(m)
}
var xxx_messageInfo_Encrypted proto.InternalMessageInfo
func (m *Encrypted) GetData() []byte {
if m != nil {
return m.Data
}
return nil
}
type Signed struct {
Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
Pubkey []byte `protobuf:"bytes,2,opt,name=pubkey,proto3" json:"pubkey,omitempty"`
Signature []byte `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Signed) Reset() { *m = Signed{} }
func (m *Signed) String() string { return proto.CompactTextString(m) }
func (*Signed) ProtoMessage() {}
func (*Signed) Descriptor() ([]byte, []int) {
return fileDescriptor_c69a0f5a734bca26, []int{8}
}
func (m *Signed) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Signed.Unmarshal(m, b)
}
func (m *Signed) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Signed.Marshal(b, m, deterministic)
}
func (m *Signed) XXX_Merge(src proto.Message) {
xxx_messageInfo_Signed.Merge(m, src)
}
func (m *Signed) XXX_Size() int {
return xxx_messageInfo_Signed.Size(m)
}
func (m *Signed) XXX_DiscardUnknown() {
xxx_messageInfo_Signed.DiscardUnknown(m)
}
var xxx_messageInfo_Signed proto.InternalMessageInfo
func (m *Signed) GetData() []byte {
if m != nil {
return m.Data
}
return nil
}
func (m *Signed) GetPubkey() []byte {
if m != nil {
return m.Pubkey
}
return nil
}
func (m *Signed) GetSignature() []byte {
if m != nil {
return m.Signature
}
return nil
}
type CheckChannelsRequest struct {
EncryptPubkey []byte `protobuf:"bytes,1,opt,name=encrypt_pubkey,json=encryptPubkey,proto3" json:"encrypt_pubkey,omitempty"`
FakeChannels map[string]uint64 `protobuf:"bytes,2,rep,name=fake_channels,json=fakeChannels,proto3" json:"fake_channels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
WaitingCloseChannels map[string]uint64 `protobuf:"bytes,3,rep,name=waiting_close_channels,json=waitingCloseChannels,proto3" json:"waiting_close_channels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *CheckChannelsRequest) Reset() { *m = CheckChannelsRequest{} }
func (m *CheckChannelsRequest) String() string { return proto.CompactTextString(m) }
func (*CheckChannelsRequest) ProtoMessage() {}
func (*CheckChannelsRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_c69a0f5a734bca26, []int{9}
}
func (m *CheckChannelsRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CheckChannelsRequest.Unmarshal(m, b)
}
func (m *CheckChannelsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CheckChannelsRequest.Marshal(b, m, deterministic)
}
func (m *CheckChannelsRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_CheckChannelsRequest.Merge(m, src)
}
func (m *CheckChannelsRequest) XXX_Size() int {
return xxx_messageInfo_CheckChannelsRequest.Size(m)
}
func (m *CheckChannelsRequest) XXX_DiscardUnknown() {
xxx_messageInfo_CheckChannelsRequest.DiscardUnknown(m)
}
var xxx_messageInfo_CheckChannelsRequest proto.InternalMessageInfo
func (m *CheckChannelsRequest) GetEncryptPubkey() []byte {
if m != nil {
return m.EncryptPubkey
}
return nil
}
func (m *CheckChannelsRequest) GetFakeChannels() map[string]uint64 {
if m != nil {
return m.FakeChannels
}
return nil
}
func (m *CheckChannelsRequest) GetWaitingCloseChannels() map[string]uint64 {
if m != nil {
return m.WaitingCloseChannels
}
return nil
}
type CheckChannelsReply struct {
NotFakeChannels map[string]uint64 `protobuf:"bytes,1,rep,name=not_fake_channels,json=notFakeChannels,proto3" json:"not_fake_channels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
ClosedChannels map[string]uint64 `protobuf:"bytes,2,rep,name=closed_channels,json=closedChannels,proto3" json:"closed_channels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *CheckChannelsReply) Reset() { *m = CheckChannelsReply{} }
func (m *CheckChannelsReply) String() string { return proto.CompactTextString(m) }
func (*CheckChannelsReply) ProtoMessage() {}
func (*CheckChannelsReply) Descriptor() ([]byte, []int) {
return fileDescriptor_c69a0f5a734bca26, []int{10}
}
func (m *CheckChannelsReply) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CheckChannelsReply.Unmarshal(m, b)
}
func (m *CheckChannelsReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CheckChannelsReply.Marshal(b, m, deterministic)
}
func (m *CheckChannelsReply) XXX_Merge(src proto.Message) {
xxx_messageInfo_CheckChannelsReply.Merge(m, src)
}
func (m *CheckChannelsReply) XXX_Size() int {
return xxx_messageInfo_CheckChannelsReply.Size(m)
}
func (m *CheckChannelsReply) XXX_DiscardUnknown() {
xxx_messageInfo_CheckChannelsReply.DiscardUnknown(m)
}
var xxx_messageInfo_CheckChannelsReply proto.InternalMessageInfo
func (m *CheckChannelsReply) GetNotFakeChannels() map[string]uint64 {
if m != nil {
return m.NotFakeChannels
}
return nil
}
func (m *CheckChannelsReply) GetClosedChannels() map[string]uint64 {
if m != nil {
return m.ClosedChannels
}
return nil
}
func init() {
proto.RegisterType((*ChannelInformationRequest)(nil), "lspd.ChannelInformationRequest")
proto.RegisterType((*ChannelInformationReply)(nil), "lspd.ChannelInformationReply")
@@ -434,6 +630,14 @@ func init() {
proto.RegisterType((*RegisterPaymentRequest)(nil), "lspd.RegisterPaymentRequest")
proto.RegisterType((*RegisterPaymentReply)(nil), "lspd.RegisterPaymentReply")
proto.RegisterType((*PaymentInformation)(nil), "lspd.PaymentInformation")
proto.RegisterType((*Encrypted)(nil), "lspd.Encrypted")
proto.RegisterType((*Signed)(nil), "lspd.Signed")
proto.RegisterType((*CheckChannelsRequest)(nil), "lspd.CheckChannelsRequest")
proto.RegisterMapType((map[string]uint64)(nil), "lspd.CheckChannelsRequest.FakeChannelsEntry")
proto.RegisterMapType((map[string]uint64)(nil), "lspd.CheckChannelsRequest.WaitingCloseChannelsEntry")
proto.RegisterType((*CheckChannelsReply)(nil), "lspd.CheckChannelsReply")
proto.RegisterMapType((map[string]uint64)(nil), "lspd.CheckChannelsReply.ClosedChannelsEntry")
proto.RegisterMapType((map[string]uint64)(nil), "lspd.CheckChannelsReply.NotFakeChannelsEntry")
}
func init() {
@@ -441,43 +645,60 @@ func init() {
}
var fileDescriptor_c69a0f5a734bca26 = []byte{
// 568 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x54, 0xff, 0x6e, 0xd3, 0x30,
0x10, 0x26, 0xac, 0xfb, 0xd1, 0x6b, 0xcb, 0xa6, 0xa3, 0x94, 0x50, 0x31, 0x11, 0x0a, 0x48, 0x11,
0x9a, 0xa6, 0x69, 0x7b, 0x82, 0x0d, 0x09, 0x81, 0xc4, 0x44, 0x65, 0x24, 0xfe, 0x8d, 0xdc, 0xf4,
0xd6, 0x5a, 0x4b, 0x6c, 0x13, 0xbb, 0x68, 0x7d, 0x07, 0x1e, 0x93, 0x97, 0xe0, 0x3f, 0x64, 0x3b,
0x61, 0xed, 0xba, 0x89, 0xff, 0xce, 0xdf, 0x7d, 0xf7, 0xdd, 0xc5, 0xdf, 0x39, 0x00, 0x85, 0xd1,
0xd3, 0x63, 0x5d, 0x29, 0xab, 0xb0, 0xe5, 0xe2, 0xd1, 0x19, 0xbc, 0xf8, 0x30, 0xe7, 0x52, 0x52,
0xf1, 0x59, 0x5e, 0xa9, 0xaa, 0xe4, 0x56, 0x28, 0xc9, 0xe8, 0xc7, 0x82, 0x8c, 0xc5, 0x01, 0xec,
0xe8, 0xc5, 0xe4, 0x9a, 0x96, 0x71, 0x94, 0x44, 0x69, 0x9b, 0xd5, 0xa7, 0xd1, 0xaf, 0x2d, 0x78,
0x7e, 0x5f, 0x95, 0x2e, 0x96, 0x88, 0xd0, 0x92, 0xbc, 0xa4, 0xba, 0xc2, 0xc7, 0x2b, 0x3a, 0x8f,
0x57, 0x75, 0x1c, 0x77, 0xae, 0x8c, 0x8d, 0xb7, 0x02, 0xd7, 0xc5, 0xf8, 0x1e, 0x0e, 0xf2, 0x20,
0x9d, 0xe5, 0x5c, 0xf3, 0x5c, 0xd8, 0x65, 0xdc, 0x4a, 0xa2, 0x74, 0x8b, 0x6d, 0xe0, 0x98, 0x40,
0xc7, 0xf2, 0x6a, 0x46, 0x36, 0xcb, 0x95, 0xbc, 0x8a, 0xb7, 0x93, 0x28, 0xdd, 0x66, 0xab, 0x10,
0xbe, 0x85, 0xde, 0x84, 0x1b, 0xca, 0xae, 0x88, 0xb2, 0xd2, 0x70, 0x1b, 0xef, 0x78, 0xa9, 0x75,
0x10, 0x87, 0xb0, 0xe7, 0xe2, 0x8a, 0x5b, 0x8a, 0x77, 0x93, 0x28, 0x8d, 0xd8, 0xbf, 0x33, 0xa6,
0xb0, 0x6f, 0x45, 0x49, 0x59, 0xa1, 0xf2, 0xeb, 0x6c, 0x4a, 0x85, 0xe5, 0xf1, 0x5e, 0x12, 0xa5,
0x3d, 0x76, 0x17, 0x76, 0xbd, 0x4a, 0x21, 0xb3, 0xb9, 0x2d, 0xf2, 0xd0, 0xab, 0x1d, 0x7a, 0xad,
0x81, 0x78, 0x0a, 0xcf, 0x9a, 0xef, 0x70, 0x3d, 0x34, 0x55, 0xe5, 0xb2, 0x12, 0x7c, 0x1a, 0x83,
0x67, 0x3f, 0xad, 0x93, 0x1f, 0x89, 0xc6, 0x4d, 0x0a, 0x0f, 0xbd, 0x71, 0x59, 0x7d, 0x87, 0x9d,
0x24, 0x4a, 0xbb, 0xac, 0x5d, 0x18, 0x3d, 0x0e, 0x76, 0x1c, 0x01, 0x7e, 0xd5, 0x24, 0x6b, 0x47,
0xfe, 0x67, 0xde, 0x18, 0x0e, 0xd6, 0xd8, 0xce, 0xb4, 0x18, 0x76, 0xed, 0x4d, 0x36, 0xe7, 0x66,
0x5e, 0x93, 0x9b, 0x23, 0x8e, 0xa0, 0xab, 0x16, 0x56, 0x2f, 0x6c, 0x26, 0xe4, 0x94, 0x6e, 0xbc,
0x81, 0x3d, 0xb6, 0x86, 0x8d, 0x8e, 0x60, 0xc0, 0x68, 0x26, 0x8c, 0xa5, 0x6a, 0xcc, 0x97, 0x25,
0x49, 0xdb, 0xcc, 0x80, 0xd0, 0x9a, 0x14, 0x6a, 0xe2, 0x0d, 0xee, 0x32, 0x1f, 0x8f, 0x06, 0xd0,
0xdf, 0x60, 0xeb, 0x62, 0x39, 0xfa, 0x1d, 0x01, 0xd6, 0xc0, 0xca, 0x52, 0xe1, 0x6b, 0xe8, 0xea,
0x80, 0xde, 0xce, 0xd7, 0x65, 0x9d, 0x1a, 0xfb, 0xe4, 0x66, 0x7c, 0x07, 0x4f, 0x1a, 0x8a, 0xa1,
0xbc, 0x22, 0xeb, 0xa7, 0xec, 0xb2, 0x5e, 0x8d, 0x7e, 0xf3, 0xa0, 0xdb, 0x96, 0x29, 0x19, 0x2b,
0xa4, 0x17, 0xae, 0x67, 0x5a, 0x85, 0xf0, 0x04, 0xfa, 0x42, 0xe6, 0xaa, 0x14, 0x72, 0x96, 0xf1,
0x52, 0x2d, 0xa4, 0x0d, 0x46, 0x86, 0xfd, 0xc3, 0x26, 0x77, 0xee, 0x53, 0x97, 0xce, 0xcd, 0x13,
0xe8, 0xab, 0x85, 0x9d, 0xa9, 0xbb, 0x15, 0xdb, 0xa1, 0xa2, 0xc9, 0xdd, 0x56, 0x9c, 0xfe, 0x89,
0xa0, 0x57, 0xdf, 0xbd, 0xb3, 0x81, 0x2a, 0xfc, 0x0e, 0xb8, 0xf9, 0x98, 0xf0, 0xd5, 0xb1, 0x7f,
0xab, 0x0f, 0x3e, 0xce, 0xe1, 0xe1, 0xc3, 0x04, 0x77, 0x9d, 0x8f, 0xf0, 0x1c, 0x3a, 0x2b, 0x46,
0x63, 0x1c, 0xf8, 0x9b, 0x9b, 0x32, 0x1c, 0xdc, 0x93, 0x09, 0x12, 0x97, 0xb0, 0x7f, 0xc7, 0x2b,
0x7c, 0x19, 0xc8, 0xf7, 0x1b, 0x3e, 0x1c, 0x3e, 0x90, 0xf5, 0x72, 0x17, 0x6f, 0xa0, 0x2f, 0xd4,
0xf1, 0xac, 0xd2, 0x79, 0xa0, 0x19, 0xaa, 0x7e, 0x8a, 0x9c, 0x2e, 0xda, 0x5f, 0x8c, 0x9e, 0x8e,
0xdd, 0x5f, 0x69, 0x1c, 0x4d, 0x76, 0xfc, 0xef, 0xe9, 0xec, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff,
0x41, 0x89, 0xc1, 0x2c, 0xac, 0x04, 0x00, 0x00,
// 846 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0xef, 0x8e, 0xdb, 0x44,
0x10, 0xaf, 0x93, 0xdc, 0xb5, 0x99, 0x38, 0x97, 0xeb, 0x36, 0x04, 0xd7, 0x6a, 0xd5, 0x60, 0xa8,
0x14, 0xa1, 0x23, 0xaa, 0xee, 0xf8, 0x80, 0xf8, 0x82, 0xee, 0x4e, 0x2d, 0x20, 0x51, 0x08, 0xae,
0x00, 0xf1, 0xc9, 0xda, 0xd8, 0x93, 0xc4, 0xc4, 0xde, 0x35, 0xf6, 0xba, 0x3d, 0xbf, 0x00, 0x9f,
0x78, 0x16, 0xde, 0x84, 0xb7, 0xe0, 0x41, 0xd0, 0xee, 0xda, 0x77, 0x76, 0xe2, 0x83, 0xde, 0xb7,
0xd9, 0xdf, 0xcc, 0xfc, 0xe6, 0xdf, 0xee, 0xd8, 0x00, 0x51, 0x96, 0x04, 0xf3, 0x24, 0xe5, 0x82,
0x93, 0x9e, 0x94, 0x9d, 0x33, 0x78, 0x7c, 0xb9, 0xa1, 0x8c, 0x61, 0xf4, 0x2d, 0x5b, 0xf1, 0x34,
0xa6, 0x22, 0xe4, 0xcc, 0xc5, 0xdf, 0x73, 0xcc, 0x04, 0x99, 0xc0, 0x61, 0x92, 0x2f, 0xb7, 0x58,
0x58, 0xc6, 0xd4, 0x98, 0xf5, 0xdd, 0xf2, 0xe4, 0xfc, 0xd9, 0x85, 0x0f, 0xdb, 0xbc, 0x92, 0xa8,
0x20, 0x04, 0x7a, 0x8c, 0xc6, 0x58, 0x7a, 0x28, 0xb9, 0xc6, 0xd3, 0xa9, 0xf3, 0x48, 0xdb, 0x0d,
0xcf, 0x84, 0xd5, 0xd5, 0xb6, 0x52, 0x26, 0x9f, 0xc2, 0xb1, 0xaf, 0xa9, 0x3d, 0x9f, 0x26, 0xd4,
0x0f, 0x45, 0x61, 0xf5, 0xa6, 0xc6, 0xac, 0xeb, 0xee, 0xe1, 0x64, 0x0a, 0x03, 0x41, 0xd3, 0x35,
0x0a, 0xcf, 0xe7, 0x6c, 0x65, 0x1d, 0x4c, 0x8d, 0xd9, 0x81, 0x5b, 0x87, 0xc8, 0x27, 0x30, 0x5c,
0xd2, 0x0c, 0xbd, 0x15, 0xa2, 0x17, 0x67, 0x54, 0x58, 0x87, 0x8a, 0xaa, 0x09, 0x12, 0x1b, 0x1e,
0x48, 0x39, 0xa5, 0x02, 0xad, 0xfb, 0x53, 0x63, 0x66, 0xb8, 0xd7, 0x67, 0x32, 0x83, 0x91, 0x08,
0x63, 0xf4, 0x22, 0xee, 0x6f, 0xbd, 0x00, 0x23, 0x41, 0xad, 0x07, 0x53, 0x63, 0x36, 0x74, 0x77,
0x61, 0x19, 0x2b, 0x0e, 0x99, 0xb7, 0x11, 0x91, 0xaf, 0x63, 0xf5, 0x75, 0xac, 0x06, 0x48, 0x4e,
0xe1, 0x83, 0xaa, 0x0e, 0x19, 0x23, 0xc1, 0x34, 0x2e, 0xd2, 0x90, 0x06, 0x16, 0x28, 0xeb, 0x47,
0xa5, 0xf2, 0x15, 0xe2, 0xa2, 0x52, 0x91, 0xa7, 0x6a, 0x70, 0x5e, 0xd9, 0xc3, 0xc1, 0xd4, 0x98,
0x99, 0x6e, 0x3f, 0xca, 0x92, 0x85, 0x1e, 0xc7, 0x09, 0x90, 0x1f, 0x12, 0x64, 0xe5, 0x44, 0xfe,
0x6f, 0x78, 0x0b, 0x38, 0x6e, 0x58, 0xcb, 0xa1, 0x59, 0x70, 0x5f, 0x5c, 0x79, 0x1b, 0x9a, 0x6d,
0x4a, 0xe3, 0xea, 0x48, 0x1c, 0x30, 0x79, 0x2e, 0x92, 0x5c, 0x78, 0x21, 0x0b, 0xf0, 0x4a, 0x0d,
0x70, 0xe8, 0x36, 0x30, 0xe7, 0x04, 0x26, 0x2e, 0xae, 0xc3, 0x4c, 0x60, 0xba, 0xa0, 0x45, 0x8c,
0x4c, 0x54, 0x39, 0x10, 0xe8, 0x2d, 0x23, 0xbe, 0x54, 0x03, 0x36, 0x5d, 0x25, 0x3b, 0x13, 0x18,
0xef, 0x59, 0x27, 0x51, 0xe1, 0xfc, 0x63, 0x00, 0x29, 0x81, 0xda, 0xa5, 0x22, 0x1f, 0x81, 0x99,
0x68, 0xf4, 0x26, 0x3f, 0xd3, 0x1d, 0x94, 0xd8, 0x37, 0x32, 0xc7, 0xe7, 0x70, 0x54, 0x99, 0x64,
0xe8, 0xa7, 0x28, 0x54, 0x96, 0xa6, 0x3b, 0x2c, 0xd1, 0x37, 0x0a, 0x94, 0xb7, 0x25, 0xc0, 0x4c,
0x84, 0x4c, 0x11, 0x97, 0x39, 0xd5, 0x21, 0xf2, 0x02, 0xc6, 0x21, 0xf3, 0x79, 0x1c, 0xb2, 0xb5,
0x47, 0x63, 0x9e, 0x33, 0xa1, 0x07, 0xa9, 0xef, 0x1f, 0xa9, 0x74, 0xe7, 0x4a, 0xf5, 0x5a, 0x4e,
0xf3, 0x05, 0x8c, 0x79, 0x2e, 0xd6, 0x7c, 0xd7, 0xe3, 0x40, 0x7b, 0x54, 0xba, 0x1b, 0x0f, 0xe7,
0x19, 0xf4, 0x5f, 0x32, 0x3f, 0x2d, 0x12, 0x81, 0x81, 0xec, 0x4f, 0x40, 0x05, 0x2d, 0x8b, 0x52,
0xb2, 0xe3, 0xc2, 0xe1, 0x9b, 0x70, 0xcd, 0xda, 0xb5, 0x3b, 0x4f, 0xc9, 0xbc, 0x7e, 0x4a, 0x4f,
0xa0, 0x9f, 0x85, 0x6b, 0x46, 0x45, 0x9e, 0x62, 0x59, 0xda, 0x0d, 0xe0, 0xfc, 0xd1, 0x85, 0xf1,
0xe5, 0x06, 0xfd, 0x6d, 0x39, 0xf5, 0xac, 0x1a, 0xd0, 0x73, 0x38, 0x42, 0x9d, 0x8d, 0x57, 0xbb,
0x2c, 0xa6, 0x3b, 0x2c, 0x51, 0x7d, 0xc3, 0xc8, 0x8f, 0x30, 0x5c, 0xd1, 0x2d, 0x7a, 0xe5, 0xe5,
0xcc, 0xac, 0xce, 0xb4, 0x3b, 0x1b, 0x9c, 0x9e, 0xcc, 0xd5, 0x3e, 0x69, 0x63, 0x9e, 0xbf, 0xa2,
0x5b, 0xac, 0xb0, 0x97, 0x4c, 0xa4, 0x85, 0x6b, 0xae, 0x6a, 0x10, 0xf9, 0x0d, 0x26, 0xef, 0x68,
0x28, 0x64, 0xe3, 0xfc, 0x88, 0x67, 0x35, 0xee, 0xae, 0xe2, 0xfe, 0xfc, 0x3f, 0xb8, 0x7f, 0xd1,
0x8e, 0x97, 0xd2, 0xaf, 0x19, 0x63, 0xfc, 0xae, 0x45, 0x65, 0x7f, 0x05, 0x0f, 0xf7, 0xd2, 0x21,
0xc7, 0xd0, 0xbd, 0x79, 0x1c, 0x52, 0x24, 0x63, 0x38, 0x78, 0x4b, 0xa3, 0x1c, 0x55, 0x6b, 0x7b,
0xae, 0x3e, 0x7c, 0xd9, 0xf9, 0xc2, 0xb0, 0xbf, 0x86, 0xc7, 0xb7, 0xc6, 0xbc, 0x0b, 0x91, 0xf3,
0x77, 0x07, 0xc8, 0x4e, 0x49, 0xf2, 0xfd, 0xfd, 0x0a, 0x0f, 0x19, 0x17, 0x5e, 0xb3, 0xc7, 0x86,
0xea, 0xc3, 0x67, 0xad, 0x7d, 0x48, 0xa2, 0x62, 0xfe, 0x3d, 0x17, 0xfb, 0x4d, 0x1e, 0xb1, 0x26,
0x4a, 0x7e, 0x82, 0x91, 0xea, 0x6f, 0xf0, 0x7e, 0xc3, 0x93, 0xc4, 0xaa, 0xc6, 0xa0, 0xc9, 0x7b,
0xe4, 0x37, 0x40, 0xfb, 0x02, 0xc6, 0x6d, 0xf1, 0xef, 0xd4, 0xd5, 0x73, 0x78, 0xd4, 0x12, 0xea,
0x2e, 0x14, 0xa7, 0x7f, 0x75, 0x60, 0x58, 0x7a, 0xcb, 0xa5, 0x86, 0x29, 0xf9, 0x59, 0x36, 0x78,
0xf7, 0xd3, 0x44, 0x9e, 0x55, 0xc5, 0xde, 0xf2, 0xa9, 0xb3, 0x9f, 0xde, 0x6e, 0x20, 0x97, 0xd3,
0x3d, 0x72, 0x0e, 0x83, 0xda, 0xda, 0x24, 0x96, 0xb6, 0xdf, 0xdf, 0xbb, 0xf6, 0xa4, 0x45, 0xa3,
0x29, 0x5e, 0xc3, 0x68, 0x67, 0xf3, 0x91, 0x27, 0xda, 0xb8, 0x7d, 0x7d, 0xda, 0xf6, 0x2d, 0x5a,
0x4d, 0x77, 0x26, 0x4b, 0xaf, 0x0d, 0x8f, 0x8c, 0xb4, 0xf9, 0xf5, 0x7a, 0xb1, 0x77, 0x01, 0xe7,
0xde, 0xc5, 0xc7, 0x30, 0x0e, 0xf9, 0x7c, 0x9d, 0x26, 0xbe, 0xd6, 0x65, 0x98, 0xbe, 0x0d, 0x7d,
0xbc, 0xe8, 0x7f, 0x97, 0x25, 0xc1, 0x42, 0xfe, 0x18, 0x2c, 0x8c, 0xe5, 0xa1, 0xfa, 0x43, 0x38,
0xfb, 0x37, 0x00, 0x00, 0xff, 0xff, 0x05, 0x11, 0xba, 0x22, 0x2f, 0x08, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@@ -495,6 +716,7 @@ type ChannelOpenerClient interface {
ChannelInformation(ctx context.Context, in *ChannelInformationRequest, opts ...grpc.CallOption) (*ChannelInformationReply, error)
OpenChannel(ctx context.Context, in *OpenChannelRequest, opts ...grpc.CallOption) (*OpenChannelReply, error)
RegisterPayment(ctx context.Context, in *RegisterPaymentRequest, opts ...grpc.CallOption) (*RegisterPaymentReply, error)
CheckChannels(ctx context.Context, in *Encrypted, opts ...grpc.CallOption) (*Encrypted, error)
}
type channelOpenerClient struct {
@@ -532,11 +754,21 @@ func (c *channelOpenerClient) RegisterPayment(ctx context.Context, in *RegisterP
return out, nil
}
func (c *channelOpenerClient) CheckChannels(ctx context.Context, in *Encrypted, opts ...grpc.CallOption) (*Encrypted, error) {
out := new(Encrypted)
err := c.cc.Invoke(ctx, "/lspd.ChannelOpener/CheckChannels", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// ChannelOpenerServer is the server API for ChannelOpener service.
type ChannelOpenerServer interface {
ChannelInformation(context.Context, *ChannelInformationRequest) (*ChannelInformationReply, error)
OpenChannel(context.Context, *OpenChannelRequest) (*OpenChannelReply, error)
RegisterPayment(context.Context, *RegisterPaymentRequest) (*RegisterPaymentReply, error)
CheckChannels(context.Context, *Encrypted) (*Encrypted, error)
}
// UnimplementedChannelOpenerServer can be embedded to have forward compatible implementations.
@@ -552,6 +784,9 @@ func (*UnimplementedChannelOpenerServer) OpenChannel(ctx context.Context, req *O
func (*UnimplementedChannelOpenerServer) RegisterPayment(ctx context.Context, req *RegisterPaymentRequest) (*RegisterPaymentReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method RegisterPayment not implemented")
}
func (*UnimplementedChannelOpenerServer) CheckChannels(ctx context.Context, req *Encrypted) (*Encrypted, error) {
return nil, status.Errorf(codes.Unimplemented, "method CheckChannels not implemented")
}
func RegisterChannelOpenerServer(s *grpc.Server, srv ChannelOpenerServer) {
s.RegisterService(&_ChannelOpener_serviceDesc, srv)
@@ -611,6 +846,24 @@ func _ChannelOpener_RegisterPayment_Handler(srv interface{}, ctx context.Context
return interceptor(ctx, in, info, handler)
}
func _ChannelOpener_CheckChannels_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Encrypted)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ChannelOpenerServer).CheckChannels(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/lspd.ChannelOpener/CheckChannels",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ChannelOpenerServer).CheckChannels(ctx, req.(*Encrypted))
}
return interceptor(ctx, in, info, handler)
}
var _ChannelOpener_serviceDesc = grpc.ServiceDesc{
ServiceName: "lspd.ChannelOpener",
HandlerType: (*ChannelOpenerServer)(nil),
@@ -627,6 +880,10 @@ var _ChannelOpener_serviceDesc = grpc.ServiceDesc{
MethodName: "RegisterPayment",
Handler: _ChannelOpener_RegisterPayment_Handler,
},
{
MethodName: "CheckChannels",
Handler: _ChannelOpener_CheckChannels_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "lspd.proto",

View File

@@ -11,6 +11,7 @@ service ChannelOpener {
returns (ChannelInformationReply) {}
rpc OpenChannel(OpenChannelRequest) returns (OpenChannelReply) {}
rpc RegisterPayment (RegisterPaymentRequest) returns (RegisterPaymentReply) {}
rpc CheckChannels(Encrypted) returns (Encrypted) {}
}
message ChannelInformationRequest {
@@ -73,3 +74,24 @@ message PaymentInformation {
int64 incoming_amount_msat = 4;
int64 outgoing_amount_msat = 5;
}
message Encrypted {
bytes data = 1;
}
message Signed {
bytes data = 1;
bytes pubkey = 2;
bytes signature = 3;
}
message CheckChannelsRequest {
bytes encrypt_pubkey = 1;
map<string, uint64> fake_channels = 2;
map<string, uint64> waiting_close_channels = 3;
}
message CheckChannelsReply {
map<string, uint64> not_fake_channels = 1;
map<string, uint64> closed_channels = 2;
}

View File

@@ -21,4 +21,8 @@ AWS_SECRET_ACCESS_KEY=<aws secret access key>
OPENCHANNEL_NOTIFICATION_TO='["Name1 <user1@domain.com>"]'
OPENCHANNEL_NOTIFICATION_CC='["Name2 <user2@domain.com>","Name3 <user3@domain.com>"]'
OPENCHANNEL_NOTIFICATION_FROM="Name4 <user4@domain.com>"
OPENCHANNEL_NOTIFICATION_FROM="Name4 <user4@domain.com>"
CHANNELMISMATCH_NOTIFICATION_TO='["Name1 <user1@domain.com>"]'
CHANNELMISMATCH_NOTIFICATION_CC='["Name2 <user2@domain.com>","Name3 <user3@domain.com>"]'
CHANNELMISMATCH_NOTIFICATION_FROM="Name4 <user4@domain.com>"

135
server.go
View File

@@ -20,6 +20,7 @@ import (
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lnwire"
"golang.org/x/sync/singleflight"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
@@ -140,6 +141,140 @@ func (s *server) OpenChannel(ctx context.Context, in *lspdrpc.OpenChannelRequest
return r.(*lspdrpc.OpenChannelReply), err
}
func getSignedEncryptedData(in *lspdrpc.Encrypted) (string, []byte, error) {
signedBlob, err := btcec.Decrypt(privateKey, in.Data)
if err != nil {
log.Printf("btcec.Decrypt(%x) error: %v", in.Data, err)
return "", nil, fmt.Errorf("btcec.Decrypt(%x) error: %w", in.Data, err)
}
var signed lspdrpc.Signed
err = proto.Unmarshal(signedBlob, &signed)
if err != nil {
log.Printf("proto.Unmarshal(%x) error: %v", signedBlob, err)
return "", nil, fmt.Errorf("proto.Unmarshal(%x) error: %w", signedBlob, err)
}
pubkey, err := btcec.ParsePubKey(signed.Pubkey, btcec.S256())
if err != nil {
log.Printf("unable to parse pubkey: %w", err)
return "", nil, fmt.Errorf("unable to parse pubkey: %w", err)
}
wireSig, err := lnwire.NewSigFromRawSignature(signed.Signature)
if err != nil {
return "", nil, fmt.Errorf("failed to decode signature: %v", err)
}
sig, err := wireSig.ToSignature()
if err != nil {
return "", nil, fmt.Errorf("failed to convert from wire format: %v",
err)
}
// The signature is over the sha256 hash of the message.
digest := chainhash.HashB(signed.Data)
if !sig.Verify(digest, pubkey) {
return "", nil, fmt.Errorf("invalid signature")
}
return hex.EncodeToString(signed.Pubkey), signed.Data, nil
}
func (s *server) CheckChannels(ctx context.Context, in *lspdrpc.Encrypted) (*lspdrpc.Encrypted, error) {
nodeID, data, err := getSignedEncryptedData(in)
if err != nil {
log.Printf("getSignedEncryptedData error: %v", err)
return nil, fmt.Errorf("getSignedEncryptedData error: %v", err)
}
var checkChannelsRequest lspdrpc.CheckChannelsRequest
err = proto.Unmarshal(data, &checkChannelsRequest)
if err != nil {
log.Printf("proto.Unmarshal(%x) error: %v", data, err)
return nil, fmt.Errorf("proto.Unmarshal(%x) error: %w", data, err)
}
notFakeChannels, err := getNotFakeChannels(nodeID, checkChannelsRequest.FakeChannels)
if err != nil {
log.Printf("getNotFakeChannels(%v) error: %v", checkChannelsRequest.FakeChannels, err)
return nil, fmt.Errorf("getNotFakeChannels(%v) error: %w", checkChannelsRequest.FakeChannels, err)
}
closedChannels, err := getClosedChannels(nodeID, checkChannelsRequest.WaitingCloseChannels)
if err != nil {
log.Printf("getNotFakeChannels(%v) error: %v", checkChannelsRequest.FakeChannels, err)
return nil, fmt.Errorf("getNotFakeChannels(%v) error: %w", checkChannelsRequest.FakeChannels, err)
}
if len(notFakeChannels) != 0 || len(closedChannels) != 0 {
err = sendChannelMismatchNotification(nodeID, notFakeChannels, closedChannels)
if err != nil {
log.Printf("sendChannelMismatchNotification() error: %v", err)
}
}
checkChannelsReply := lspdrpc.CheckChannelsReply{
NotFakeChannels: notFakeChannels,
ClosedChannels: closedChannels,
}
dataReply, err := proto.Marshal(&checkChannelsReply)
if err != nil {
log.Printf("proto.Marshall() error: %v", err)
return nil, fmt.Errorf("proto.Marshal() error: %w", err)
}
pubkey, err := btcec.ParsePubKey(checkChannelsRequest.EncryptPubkey, btcec.S256())
if err != nil {
log.Printf("unable to parse pubkey: %v", err)
return nil, fmt.Errorf("unable to parse pubkey: %w", err)
}
encrypted, err := btcec.Encrypt(pubkey, dataReply)
if err != nil {
log.Printf("btcec.Encrypt() error: %v", err)
return nil, fmt.Errorf("btcec.Encrypt() error: %w", err)
}
return &lspdrpc.Encrypted{Data: encrypted}, nil
}
func getNotFakeChannels(nodeID string, channelPoints map[string]uint64) (map[string]uint64, error) {
var r map[string]uint64
channels, err := getNodeChannels(nodeID)
if err != nil {
return nil, err
}
for _, c := range channels {
if h, ok := channelPoints[c.ChannelPoint]; ok {
sid := lnwire.NewShortChanIDFromInt(c.ChanId)
if !sid.IsFake() {
r[c.ChannelPoint] = h
}
}
}
return r, nil
}
func getClosedChannels(nodeID string, channelPoints map[string]uint64) (map[string]uint64, error) {
var r map[string]uint64
waitingCloseChannels, err := getWaitingCloseChannels(nodeID)
if err != nil {
return nil, err
}
wcc := make(map[string]struct{})
for _, c := range waitingCloseChannels {
wcc[c.Channel.ChannelPoint] = struct{}{}
}
for c, h := range channelPoints {
if _, ok := wcc[c]; !ok {
r[c] = h
}
}
return r, nil
}
func getWaitingCloseChannels(nodeID string) ([]*lnrpc.PendingChannelsResponse_WaitingCloseChannel, error) {
clientCtx := metadata.AppendToOutgoingContext(context.Background(), "macaroon", os.Getenv("LND_MACAROON_HEX"))
pendingResponse, err := client.PendingChannels(clientCtx, &lnrpc.PendingChannelsRequest{})
if err != nil {
return nil, err
}
var waitingCloseChannels []*lnrpc.PendingChannelsResponse_WaitingCloseChannel
for _, p := range pendingResponse.WaitingCloseChannels {
if p.Channel.RemoteNodePub == nodeID {
waitingCloseChannels = append(waitingCloseChannels, p)
}
}
return waitingCloseChannels, nil
}
func getNodeChannels(nodeID string) ([]*lnrpc.Channel, error) {
clientCtx := metadata.AppendToOutgoingContext(context.Background(), "macaroon", os.Getenv("LND_MACAROON_HEX"))
listResponse, err := client.ListChannels(clientCtx, &lnrpc.ListChannelsRequest{})