Merge pull request #10 from joostjager/dev

loop+loopd config flags
pull/14/head
Olaoluwa Osuntokun 5 years ago committed by GitHub
commit ed98051daf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,25 @@
language: go
cache:
directories:
- $GOCACHE
- $GOPATH/pkg/mod
- $GOPATH/src/github.com/btcsuite
- $GOPATH/src/github.com/golang
- $GOPATH/src/gopkg.in/alecthomas
go:
- "1.11.x"
env:
global:
- GOCACHE=$HOME/.go-build
sudo: required
script:
- export GO111MODULE=on
- make unit
after_script:
- echo "Uploading to termbin.com..." && find *.log | xargs -I{} sh -c "cat {} | nc termbin.com 9999 | xargs -r0 printf '{} uploaded to %s'"
- echo "Uploading to file.io..." && tar -zcvO *.log | curl -s -F 'file=@-;filename=logs.tar.gz' https://file.io | xargs -r0 printf 'logs.tar.gz uploaded to %s\n'

@ -0,0 +1,15 @@
PKG := github.com/lightninglabs/loop
GOTEST := GO111MODULE=on go test -v
GOLIST := go list $(PKG)/... | grep -v '/vendor/'
XARGS := xargs -L 1
TEST_FLAGS = -test.timeout=20m
UNIT := $(GOLIST) | $(XARGS) env $(GOTEST) $(TEST_FLAGS)
unit:
@$(call print, "Running unit tests.")
$(UNIT)

@ -4,9 +4,7 @@ import (
"context" "context"
"fmt" "fmt"
"github.com/btcsuite/btcutil"
"github.com/lightninglabs/loop/looprpc" "github.com/lightninglabs/loop/looprpc"
"github.com/lightninglabs/loop/swap"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
@ -97,81 +95,3 @@ func loopOut(ctx *cli.Context) error {
return nil return nil
} }
var termsCommand = cli.Command{
Name: "terms",
Usage: "show current server swap terms",
Action: terms,
}
func terms(ctx *cli.Context) error {
client, cleanup, err := getClient(ctx)
if err != nil {
return err
}
defer cleanup()
terms, err := client.GetLoopOutTerms(
context.Background(), &looprpc.TermsRequest{},
)
if err != nil {
return err
}
fmt.Printf("Amount: %d - %d\n",
btcutil.Amount(terms.MinSwapAmount),
btcutil.Amount(terms.MaxSwapAmount),
)
if err != nil {
return err
}
printTerms := func(terms *looprpc.TermsResponse) {
fmt.Printf("Amount: %d - %d\n",
btcutil.Amount(terms.MinSwapAmount),
btcutil.Amount(terms.MaxSwapAmount),
)
fmt.Printf("Fee: %d + %.4f %% (%d prepaid)\n",
btcutil.Amount(terms.SwapFeeBase),
swap.FeeRateAsPercentage(terms.SwapFeeRate),
btcutil.Amount(terms.PrepayAmt),
)
fmt.Printf("Cltv delta: %v blocks\n", terms.CltvDelta)
}
fmt.Println("Loop Out")
fmt.Println("--------")
printTerms(terms)
return nil
}
var monitorCommand = cli.Command{
Name: "monitor",
Usage: "monitor progress of any active swaps",
Description: "Allows the user to monitor progress of any active swaps",
Action: monitor,
}
func monitor(ctx *cli.Context) error {
client, cleanup, err := getClient(ctx)
if err != nil {
return err
}
defer cleanup()
stream, err := client.Monitor(
context.Background(), &looprpc.MonitorRequest{})
if err != nil {
return err
}
for {
swap, err := stream.Recv()
if err != nil {
return fmt.Errorf("recv: %v", err)
}
logSwap(swap)
}
}

@ -17,8 +17,6 @@ import (
) )
var ( var (
loopdAddress = "localhost:11010"
// Define route independent max routing fees. We have currently no way // Define route independent max routing fees. We have currently no way
// to get a reliable estimate of the routing fees. Best we can do is // to get a reliable estimate of the routing fees. Best we can do is
// the minimum routing fees, which is not very indicative. // the minimum routing fees, which is not very indicative.
@ -38,6 +36,13 @@ func main() {
app.Version = "0.0.1" app.Version = "0.0.1"
app.Name = "loop" app.Name = "loop"
app.Usage = "control plane for your loopd" app.Usage = "control plane for your loopd"
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "loopd",
Value: "localhost:11010",
Usage: "loopd daemon address host:port",
},
}
app.Commands = []cli.Command{ app.Commands = []cli.Command{
loopOutCommand, termsCommand, monitorCommand, loopOutCommand, termsCommand, monitorCommand,
} }
@ -49,6 +54,7 @@ func main() {
} }
func getClient(ctx *cli.Context) (looprpc.SwapClientClient, func(), error) { func getClient(ctx *cli.Context) (looprpc.SwapClientClient, func(), error) {
loopdAddress := ctx.GlobalString("loopd")
conn, err := getClientConn(loopdAddress) conn, err := getClientConn(loopdAddress)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err

@ -0,0 +1,38 @@
package main
import (
"context"
"fmt"
"github.com/lightninglabs/loop/looprpc"
"github.com/urfave/cli"
)
var monitorCommand = cli.Command{
Name: "monitor",
Usage: "monitor progress of any active swaps",
Description: "Allows the user to monitor progress of any active swaps",
Action: monitor,
}
func monitor(ctx *cli.Context) error {
client, cleanup, err := getClient(ctx)
if err != nil {
return err
}
defer cleanup()
stream, err := client.Monitor(
context.Background(), &looprpc.MonitorRequest{})
if err != nil {
return err
}
for {
swap, err := stream.Recv()
if err != nil {
return fmt.Errorf("recv: %v", err)
}
logSwap(swap)
}
}

@ -0,0 +1,61 @@
package main
import (
"context"
"fmt"
"github.com/btcsuite/btcutil"
"github.com/lightninglabs/loop/swap"
"github.com/lightninglabs/loop/looprpc"
"github.com/urfave/cli"
)
var termsCommand = cli.Command{
Name: "terms",
Usage: "show current server swap terms",
Action: terms,
}
func terms(ctx *cli.Context) error {
client, cleanup, err := getClient(ctx)
if err != nil {
return err
}
defer cleanup()
terms, err := client.GetLoopOutTerms(
context.Background(), &looprpc.TermsRequest{},
)
if err != nil {
return err
}
fmt.Printf("Amount: %d - %d\n",
btcutil.Amount(terms.MinSwapAmount),
btcutil.Amount(terms.MaxSwapAmount),
)
if err != nil {
return err
}
printTerms := func(terms *looprpc.TermsResponse) {
fmt.Printf("Amount: %d - %d\n",
btcutil.Amount(terms.MinSwapAmount),
btcutil.Amount(terms.MaxSwapAmount),
)
fmt.Printf("Fee: %d + %.4f %% (%d prepaid)\n",
btcutil.Amount(terms.SwapFeeBase),
swap.FeeRateAsPercentage(terms.SwapFeeRate),
btcutil.Amount(terms.PrepayAmt),
)
fmt.Printf("Cltv delta: %v blocks\n", terms.CltvDelta)
}
fmt.Println("Loop Out")
fmt.Println("--------")
printTerms(terms)
return nil
}

@ -0,0 +1,30 @@
package main
type lndConfig struct {
Host string `long:"host" description:"lnd instance rpc address"`
MacaroonPath string `long:"macaroonpath" description:"Path to lnd macaroon"`
TLSPath string `long:"tlspath" description:"Path to lnd tls certificate"`
}
type viewParameters struct{}
type config struct {
Insecure bool `long:"insecure" description:"disable tls"`
Network string `long:"network" description:"network to run on" choice:"regtest" choice:"testnet" choice:"mainnet" choice:"simnet"`
SwapServer string `long:"swapserver" description:"swap server address host:port"`
Listen string `long:"listen" description:"address to listen on for rpc lcients"`
Lnd *lndConfig `group:"lnd" namespace:"lnd"`
View viewParameters `command:"view" alias:"v" description:"View all swaps in the database. This command can only be executed when loopd is not running."`
}
var defaultConfig = config{
Network: "mainnet",
SwapServer: "swap.lightning.today:11009",
Listen: "localhost:11010",
Insecure: false,
Lnd: &lndConfig{
Host: "localhost:10009",
},
}

@ -12,20 +12,21 @@ import (
"github.com/lightninglabs/loop" "github.com/lightninglabs/loop"
"github.com/lightninglabs/loop/looprpc" "github.com/lightninglabs/loop/looprpc"
"github.com/urfave/cli"
"google.golang.org/grpc" "google.golang.org/grpc"
) )
// daemon runs swapd in daemon mode. It will listen for grpc connections, // daemon runs loopd in daemon mode. It will listen for grpc connections,
// execute commands and pass back swap status information. // execute commands and pass back swap status information.
func daemon(ctx *cli.Context) error { func daemon(config *config) error {
lnd, err := getLnd(ctx) lnd, err := getLnd(config.Network, config.Lnd)
if err != nil { if err != nil {
return err return err
} }
defer lnd.Close() defer lnd.Close()
swapClient, cleanup, err := getClient(ctx, &lnd.LndServices) swapClient, cleanup, err := getClient(
config.Network, config.SwapServer, config.Insecure, &lnd.LndServices,
)
if err != nil { if err != nil {
return err return err
} }
@ -48,7 +49,7 @@ func daemon(ctx *cli.Context) error {
} }
} }
// Instantiate the swapd gRPC server. // Instantiate the loopd gRPC server.
server := swapClientServer{ server := swapClientServer{
impl: swapClient, impl: swapClient,
lnd: &lnd.LndServices, lnd: &lnd.LndServices,
@ -60,10 +61,10 @@ func daemon(ctx *cli.Context) error {
// Next, Start the gRPC server listening for HTTP/2 connections. // Next, Start the gRPC server listening for HTTP/2 connections.
logger.Infof("Starting RPC listener") logger.Infof("Starting RPC listener")
lis, err := net.Listen("tcp", defaultListenAddr) lis, err := net.Listen("tcp", config.Listen)
if err != nil { if err != nil {
return fmt.Errorf("RPC server unable to listen on %s", return fmt.Errorf("RPC server unable to listen on %s",
defaultListenAddr) config.Listen)
} }
defer lis.Close() defer lis.Close()
@ -134,7 +135,7 @@ func daemon(ctx *cli.Context) error {
interruptChannel := make(chan os.Signal, 1) interruptChannel := make(chan os.Signal, 1)
signal.Notify(interruptChannel, os.Interrupt) signal.Notify(interruptChannel, os.Interrupt)
// Run until the users terminates swapd or an error occurred. // Run until the users terminates loopd or an error occurred.
select { select {
case <-interruptChannel: case <-interruptChannel:
logger.Infof("Received SIGINT (Ctrl+C).") logger.Infof("Received SIGINT (Ctrl+C).")

@ -11,7 +11,7 @@ import (
// it. // it.
var ( var (
backendLog = btclog.NewBackend(logWriter{}) backendLog = btclog.NewBackend(logWriter{})
logger = backendLog.Logger("SWAPD") logger = backendLog.Logger("LOOPD")
) )
// logWriter implements an io.Writer that outputs to both standard output and // logWriter implements an io.Writer that outputs to both standard output and

@ -3,22 +3,23 @@ package main
import ( import (
"fmt" "fmt"
"os" "os"
"path/filepath"
"sync" "sync"
flags "github.com/jessevdk/go-flags"
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
"github.com/lightninglabs/loop" "github.com/lightninglabs/loop"
"github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lntypes"
"github.com/urfave/cli"
) )
const ( const (
defaultListenPort = 11010
defaultConfTarget = int32(2) defaultConfTarget = int32(2)
) )
var ( var (
defaultListenAddr = fmt.Sprintf("localhost:%d", defaultListenPort) loopDirBase = btcutil.AppDataDir("loop", false)
defaultSwapletDir = btcutil.AppDataDir("swaplet", false) defaultConfigFilename = "loopd.conf"
swaps = make(map[lntypes.Hash]loop.SwapInfo) swaps = make(map[lntypes.Hash]loop.SwapInfo)
subscribers = make(map[int]chan<- interface{}) subscribers = make(map[int]chan<- interface{})
@ -27,47 +28,58 @@ var (
) )
func main() { func main() {
app := cli.NewApp() err := start()
if err != nil {
app.Flags = []cli.Flag{ fmt.Println(err)
cli.StringFlag{ }
Name: "network", }
Value: "mainnet",
Usage: "network to run on (regtest, testnet, mainnet)", func start() error {
}, config := defaultConfig
cli.StringFlag{
Name: "lnd", // Parse command line flags.
Value: "localhost:10009", parser := flags.NewParser(&config, flags.Default)
Usage: "lnd instance rpc address host:port", parser.SubcommandsOptional = true
},
cli.StringFlag{ _, err := parser.Parse()
Name: "swapserver", if e, ok := err.(*flags.Error); ok && e.Type == flags.ErrHelp {
Value: "swap.lightning.today:11009", return nil
Usage: "swap server address host:port",
},
cli.StringFlag{
Name: "macaroonpath",
Usage: "path to lnd macaroon",
},
cli.StringFlag{
Name: "tlspath",
Usage: "path to lnd tls certificate",
},
cli.BoolFlag{
Name: "insecure",
Usage: "disable tls",
},
} }
app.Name = "loopd" if err != nil {
app.Version = "0.0.1" return err
app.Usage = "Lightning Loop Client Daemon"
app.Commands = []cli.Command{
viewCommand,
} }
app.Action = daemon
err := app.Run(os.Args) // Parse ini file.
loopDir := filepath.Join(loopDirBase, config.Network)
if err := os.MkdirAll(loopDir, os.ModePerm); err != nil {
return err
}
configFile := filepath.Join(loopDir, defaultConfigFilename)
if err := flags.IniParse(configFile, &config); err != nil {
// If it's a parsing related error, then we'll return
// immediately, otherwise we can proceed as possibly the config
// file doesn't exist which is OK.
if _, ok := err.(*flags.IniError); ok {
return err
}
}
// Parse command line flags again to restore flags overwritten by ini
// parse.
_, err = parser.Parse()
if err != nil { if err != nil {
fmt.Println(err) return err
} }
// Execute command.
if parser.Active == nil {
return daemon(&config)
}
if parser.Active.Name == "view" {
return view(&config)
}
return fmt.Errorf("unimplemented command %v", parser.Active.Name)
} }

@ -6,33 +6,26 @@ import (
"github.com/lightninglabs/loop" "github.com/lightninglabs/loop"
"github.com/lightninglabs/loop/lndclient" "github.com/lightninglabs/loop/lndclient"
"github.com/urfave/cli"
) )
// getLnd returns an instance of the lnd services proxy. // getLnd returns an instance of the lnd services proxy.
func getLnd(ctx *cli.Context) (*lndclient.GrpcLndServices, error) { func getLnd(network string, cfg *lndConfig) (*lndclient.GrpcLndServices, error) {
network := ctx.GlobalString("network") return lndclient.NewLndServices(
cfg.Host, "client", network, cfg.MacaroonPath, cfg.TLSPath,
return lndclient.NewLndServices(ctx.GlobalString("lnd"),
"client", network, ctx.GlobalString("macaroonpath"),
ctx.GlobalString("tlspath"),
) )
} }
// getClient returns an instance of the swap client. // getClient returns an instance of the swap client.
func getClient(ctx *cli.Context, func getClient(network, swapServer string, insecure bool,
lnd *lndclient.LndServices) (*loop.Client, func(), error) { lnd *lndclient.LndServices) (*loop.Client, func(), error) {
network := ctx.GlobalString("network")
storeDir, err := getStoreDir(network) storeDir, err := getStoreDir(network)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
swapClient, cleanUp, err := loop.NewClient( swapClient, cleanUp, err := loop.NewClient(
storeDir, ctx.GlobalString("swapserver"), storeDir, swapServer, insecure, lnd,
ctx.GlobalBool("insecure"), lnd,
) )
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -42,7 +35,7 @@ func getClient(ctx *cli.Context,
} }
func getStoreDir(network string) (string, error) { func getStoreDir(network string) (string, error) {
dir := filepath.Join(defaultSwapletDir, network) dir := filepath.Join(loopDirBase, network)
if err := os.MkdirAll(dir, os.ModePerm); err != nil { if err := os.MkdirAll(dir, os.ModePerm); err != nil {
return "", err return "", err
} }

@ -5,34 +5,24 @@ import (
"strconv" "strconv"
"github.com/lightninglabs/loop/swap" "github.com/lightninglabs/loop/swap"
"github.com/urfave/cli"
) )
var viewCommand = cli.Command{
Name: "view",
Usage: `view all swaps in the database. This command can only be
executed when swapd is not running.`,
Description: `
Show all pending and completed swaps.`,
Action: view,
}
// view prints all swaps currently in the database. // view prints all swaps currently in the database.
func view(ctx *cli.Context) error { func view(config *config) error {
network := ctx.GlobalString("network") chainParams, err := swap.ChainParamsFromNetwork(config.Network)
chainParams, err := swap.ChainParamsFromNetwork(network)
if err != nil { if err != nil {
return err return err
} }
lnd, err := getLnd(ctx) lnd, err := getLnd(config.Network, config.Lnd)
if err != nil { if err != nil {
return err return err
} }
defer lnd.Close() defer lnd.Close()
swapClient, cleanup, err := getClient(ctx, &lnd.LndServices) swapClient, cleanup, err := getClient(
config.Network, config.SwapServer, config.Insecure, &lnd.LndServices,
)
if err != nil { if err != nil {
return err return err
} }
@ -43,6 +33,10 @@ func view(ctx *cli.Context) error {
return err return err
} }
if len(swaps) == 0 {
fmt.Printf("No swaps\n")
}
for _, s := range swaps { for _, s := range swaps {
htlc, err := swap.NewHtlc( htlc, err := swap.NewHtlc(
s.Contract.CltvExpiry, s.Contract.CltvExpiry,

@ -45,7 +45,7 @@ func NewLndServices(lndAddress string, application string,
*GrpcLndServices, error) { *GrpcLndServices, error) {
// Setup connection with lnd // Setup connection with lnd
logger.Infof("Creating lnd connection") logger.Infof("Creating lnd connection to %v", lndAddress)
conn, err := getClientConn(lndAddress, network, macPath, tlsPath) conn, err := getClientConn(lndAddress, network, macPath, tlsPath)
if err != nil { if err != nil {
return nil, err return nil, err

Loading…
Cancel
Save