Skip to content
This repository was archived by the owner on Jul 19, 2023. It is now read-only.

Commit

Permalink
Replace direct lnd dependency with references to .proto file
Browse files Browse the repository at this point in the history
  • Loading branch information
meeDamian committed Jan 24, 2020
1 parent 864114c commit f89a64c
Show file tree
Hide file tree
Showing 14 changed files with 17,845 additions and 109 deletions.
40 changes: 39 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ GOBUILD := $(PREFIX) go build -v -trimpath -mod=readonly $(BUILD_FLAGS)

SRC := $(shell find . -type f -name '*.go') go.mod go.sum

# Define lnd version being used on the backend
LND_VERSION = v0.9.0-beta

bin/invoicer: $(SRC)
$(PREFIX) go build -v -o $@

Expand Down Expand Up @@ -35,10 +38,45 @@ run: $(SRC)
clean:
rm -rf bin/*

#
# PROTO stuff
#
ln/lnd:
mkdir -p $@

ln/lnd/google/api:
mkdir -p $@

# Fetch rpc.proto files from https://github.com/lightningnetwork/lnd
ln/lnd/rpc.proto: ln/lnd/%: ln/lnd
wget -qO - https://raw.githubusercontent.com/lightningnetwork/lnd/$(LND_VERSION)/lnrpc/$* | \
sed 's|github.com/lightningnetwork/lnd/lnrpc|lnd|' > $@

# Fetch .proto files that ln/lnd/rpc.proto depends on
# Files fetched from https://github.com/googleapis/googleapis are:
# * google/api/annotations.proto, and
# * google/api/http.proto
$(patsubst %, ln/lnd/google/api/%.proto, annotations http): ln/lnd/%: ln/lnd/google/api
wget -qO $@ https://raw.githubusercontent.com/googleapis/googleapis/master/$*

clean-proto:
rm -rf ln/lnd/

proto: clean-proto ln/lnd/rpc.proto ln/lnd/google/api/annotations.proto ln/lnd/google/api/http.proto
go generate ./ln/...

# Linter install instructions are here:
# https://github.com/golangci/golangci-lint#install
lint:
golangci-lint run ./...

lint-all:
golangci-lint run --enable-all ./...

static/index.html:
mkdir -p static
curl -s https://api.github.com/repos/lncm/donations/releases/latest \
| jq -r '.assets[0].browser_download_url' \
| wget -O $@ -qi -

.PHONY: run clean static/index.html
.PHONY: run proto clean clean-proto static/index.html
2 changes: 1 addition & 1 deletion bitcoind/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func (b Bitcoind) sendRequest(method string, params ...interface{}) (response []
}

if resBody.Error != nil {
return nil, fmt.Errorf("bitcoind error (%d): %w", resBody.Error.Code, resBody.Error.Message)
return nil, fmt.Errorf("bitcoind error (%d): %s", resBody.Error.Code, resBody.Error.Message)
}

return resBody.Result, nil
Expand Down
40 changes: 0 additions & 40 deletions clightning/client.go

This file was deleted.

24 changes: 11 additions & 13 deletions common/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ type (
Bitcoind Bitcoind `toml:"bitcoind"`

// [lnd] section in the `--config` file that defines Lnd's setup
Lnd Lnd `toml:"lnd"`
Lnd LndConfig `toml:"lnd"`

// An optional list of user:password pairs that will get granted access to the /history endpoint
Users map[string]string `toml:"users"`
Expand All @@ -44,25 +44,23 @@ type (
Pass string `toml:"pass"`
}

// Lnd config
Lnd struct {
Macaroons struct {
// This is needed to generate new invoices
Invoice string `toml:"invoice"`

// This is needed to check status of invoices (and if enabled access `/history` endpoint)
ReadOnly string `toml:"readonly"`
}

LndConfig struct {
Host string `toml:"host"`
Port int64 `toml:"port"`

// TLS certificate is usually located in `~/.lnd/tls.cert`
TLS string `toml:"tls"`

// Macaroons are usually located in `~/.lnd/data/chain/bitcoin/mainnet/`
Macaroons struct {
// This is needed to generate new invoices
Invoice string `toml:"invoice"`

// This is needed to check status of invoices (and if enabled access `/history` endpoint)
ReadOnly string `toml:"readonly"`
} `toml:"macaroon"`

// How many times try to talk to LND before committing suicide
KillCount *int `toml:"kill-count"`
Macaroons Macaroons `toml:"macaroon"`
}
)

Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ require (
github.com/gin-gonic/gin v1.4.0
github.com/go-playground/locales v0.12.1 // indirect
github.com/go-playground/universal-translator v0.16.0 // indirect
github.com/golang/protobuf v1.3.1
github.com/leodido/go-urn v1.1.0 // indirect
github.com/lightningnetwork/lnd v0.7.1-beta
github.com/pelletier/go-toml v1.4.0
github.com/sirupsen/logrus v1.4.2
google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922
google.golang.org/grpc v1.23.0
gopkg.in/go-playground/validator.v9 v9.29.1
gopkg.in/macaroon.v2 v2.1.0
Expand Down
20 changes: 20 additions & 0 deletions ln/ln.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package ln

import (
"context"

"github.com/lncm/invoicer/common"
)

type LightningClient interface {
NewAddress(ctx context.Context, bech32 bool) (string, error)
Info(ctx context.Context) (common.Info, error)
NewInvoice(ctx context.Context, amount int64, desc string) (string, string, error)
Status(ctx context.Context, hash string) (common.Status, error)
StatusWait(ctx context.Context, hash string) (common.Status, error)
History(ctx context.Context) (common.Invoices, error)
}

func Start(conf common.LndConfig) (Lnd, error) {
return startClient(conf)
}
18 changes: 18 additions & 0 deletions ln/ln_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package ln

import (
"testing"

"github.com/lncm/invoicer/common"
)

func TestNew(t *testing.T) {
conf := common.LndConfig{
Host: "localhost",
Port: 10009,
TLS: "../tls.cert",
Macaroons: common.Macaroons{},
}

_, _ = Start(conf)
}
72 changes: 36 additions & 36 deletions lnd/client.go → ln/lnd.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
package lnd
//go:generate protoc --go_out=plugins=grpc,paths=source_relative:./lnd/ -Ilnd/ lnd/rpc.proto

package ln

import (
"context"
Expand All @@ -8,7 +10,6 @@ import (
"time"

"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/macaroons"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
Expand All @@ -18,16 +19,14 @@ import (
)

const (
ClientName = "lnd"

DefaultHostname = "localhost"
DefaultPort = 10009
DefaultTLS = "~/.lncm/tls.cert"
DefaultInvoice = "~/.lncm/invoice.macaroon"
DefaultReadOnly = "~/.lncm/readonly.macaroon"
DefaultKillCount = 4
DefaultHostname = "localhost"
DefaultPort = 10009
DefaultTLS = "~/.lncm/tls.cert"
DefaultInvoice = "~/.lncm/invoice.macaroon"
DefaultReadOnly = "~/.lncm/readonly.macaroon"
)

// LndConfig config
type Lnd struct {
// Used to generate invoices and monitor their status
invoiceClient lnrpc.LightningClient
Expand Down Expand Up @@ -147,11 +146,7 @@ func (lnd Lnd) History(ctx context.Context) (invoices common.Invoices, err error
return
}

func (lnd Lnd) checkConnectionStatus(killCount int) {
if killCount == 0 {
return
}

func (lnd Lnd) checkConnectionStatus() {
failures := 0

for {
Expand All @@ -169,10 +164,6 @@ func (lnd Lnd) checkConnectionStatus(killCount int) {

cancel()

if failures >= killCount {
log.WithField("count", failures).WithField("final", true).Panic("lnd unreachable")
}

if failures > 0 {
log.WithField("count", failures).Printf("lnd unreachable")
}
Expand All @@ -181,7 +172,7 @@ func (lnd Lnd) checkConnectionStatus(killCount int) {
}
}

func getClient(creds credentials.TransportCredentials, fullHostname, file string) lnrpc.LightningClient {
func getClient(transportCredentials credentials.TransportCredentials, fullHostname, file string) lnrpc.LightningClient {
macaroonBytes, err := ioutil.ReadFile(file)
if err != nil {
panic(fmt.Sprintln("Cannot read macaroon file", err))
Expand All @@ -196,9 +187,9 @@ func getClient(creds credentials.TransportCredentials, fullHostname, file string
defer cancel()

connection, err := grpc.DialContext(ctx, fullHostname, []grpc.DialOption{
grpc.WithTransportCredentials(creds),
grpc.WithBlock(),
grpc.WithPerRPCCredentials(macaroons.NewMacaroonCredential(mac)),
grpc.WithTransportCredentials(transportCredentials),
grpc.WithPerRPCCredentials(newCreds(macaroonBytes)),
}...)
if err != nil {
panic(fmt.Errorf("unable to connect to %s: %w", fullHostname, err))
Expand All @@ -207,7 +198,7 @@ func getClient(creds credentials.TransportCredentials, fullHostname, file string
return lnrpc.NewLightningClient(connection)
}

func New(conf common.Lnd) (lnd Lnd) {
func startClient(conf common.LndConfig) (c Lnd, err error) {
if conf.Host == "" {
conf.Host = DefaultHostname
}
Expand All @@ -231,32 +222,41 @@ func New(conf common.Lnd) (lnd Lnd) {
}
conf.Macaroons.ReadOnly = common.CleanAndExpandPath(conf.Macaroons.ReadOnly)

creds, err := credentials.NewClientTLSFromFile(conf.TLS, conf.Host)
transportCredentials, err := credentials.NewClientTLSFromFile(conf.TLS, conf.Host)
if err != nil {
panic(err)
return c, err
}

hostname := fmt.Sprintf("%s:%d", conf.Host, conf.Port)

invoiceClient := getClient(creds, hostname, conf.Macaroons.Invoice)
readOnlyClient := getClient(transportCredentials, hostname, conf.Macaroons.ReadOnly)
invoiceClient := getClient(transportCredentials, hostname, conf.Macaroons.Invoice)

notifier, err := NewNotifier(invoiceClient)
if err != nil {
panic(err)
return c, err
}

lnd = Lnd{
c = Lnd{
invoiceClient: invoiceClient,
readOnlyClient: getClient(creds, hostname, conf.Macaroons.ReadOnly),
readOnlyClient: readOnlyClient,
notifier: notifier,
}

if conf.KillCount == nil {
// `hah` assignment is silly, but necessary…
hah := DefaultKillCount
conf.KillCount = &hah
}
go c.checkConnectionStatus()

return c, nil
}

type rpcCreds map[string]string

go lnd.checkConnectionStatus(*conf.KillCount)
func (m rpcCreds) RequireTransportSecurity() bool { return true }
func (m rpcCreds) GetRequestMetadata(_ context.Context, _ ...string) (map[string]string, error) {
return m, nil
}

return lnd
func newCreds(bytes []byte) rpcCreds {
creds := make(map[string]string)
creds["macaroon"] = hex.EncodeToString(bytes)
return creds
}
31 changes: 31 additions & 0 deletions ln/lnd/google/api/annotations.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) 2015, Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package google.api;

import "google/api/http.proto";
import "google/protobuf/descriptor.proto";

option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations";
option java_multiple_files = true;
option java_outer_classname = "AnnotationsProto";
option java_package = "com.google.api";
option objc_class_prefix = "GAPI";

extend google.protobuf.MethodOptions {
// See `HttpRule`.
HttpRule http = 72295728;
}
Loading

0 comments on commit f89a64c

Please sign in to comment.