Skip to content

Commit 53dc21f

Browse files
authored
Merge pull request #101 from guggero/lsat-integration
LSAT aware client interceptor
2 parents a9033ba + 1650f3a commit 53dc21f

21 files changed

+2021
-186
lines changed

client.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/btcsuite/btcutil"
1313
"github.com/lightninglabs/loop/lndclient"
1414
"github.com/lightninglabs/loop/loopdb"
15+
"github.com/lightninglabs/loop/lsat"
1516
"github.com/lightninglabs/loop/swap"
1617
"github.com/lightninglabs/loop/sweep"
1718
"github.com/lightningnetwork/lnd/lntypes"
@@ -48,8 +49,15 @@ var (
4849
ErrSweepConfTargetTooFar = errors.New("sweep confirmation target is " +
4950
"beyond swap expiration height")
5051

52+
// serverRPCTimeout is the maximum time a gRPC request to the server
53+
// should be allowed to take.
5154
serverRPCTimeout = 30 * time.Second
5255

56+
// globalCallTimeout is the maximum time any call of the client to the
57+
// server is allowed to take, including the time it may take to get
58+
// and pay for an LSAT token.
59+
globalCallTimeout = serverRPCTimeout + lsat.PaymentTimeout
60+
5361
republishDelay = 10 * time.Second
5462
)
5563

@@ -71,14 +79,21 @@ type Client struct {
7179

7280
// NewClient returns a new instance to initiate swaps with.
7381
func NewClient(dbDir string, serverAddress string, insecure bool,
74-
lnd *lndclient.LndServices) (*Client, func(), error) {
82+
tlsPathServer string, lnd *lndclient.LndServices) (*Client, func(),
83+
error) {
7584

7685
store, err := loopdb.NewBoltSwapStore(dbDir, lnd.ChainParams)
7786
if err != nil {
7887
return nil, nil, err
7988
}
89+
lsatStore, err := lsat.NewFileStore(dbDir)
90+
if err != nil {
91+
return nil, nil, err
92+
}
8093

81-
swapServerClient, err := newSwapServerClient(serverAddress, insecure)
94+
swapServerClient, err := newSwapServerClient(
95+
serverAddress, insecure, tlsPathServer, lsatStore, lnd,
96+
)
8297
if err != nil {
8398
return nil, nil, err
8499
}
@@ -87,6 +102,7 @@ func NewClient(dbDir string, serverAddress string, insecure bool,
87102
LndServices: lnd,
88103
Server: swapServerClient,
89104
Store: store,
105+
LsatStore: lsatStore,
90106
CreateExpiryTimer: func(d time.Duration) <-chan time.Time {
91107
return time.NewTimer(d).C
92108
},

cmd/loop/lsat.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"encoding/hex"
7+
"fmt"
8+
"time"
9+
10+
"github.com/lightninglabs/loop/looprpc"
11+
"github.com/lightninglabs/loop/lsat"
12+
"github.com/urfave/cli"
13+
"gopkg.in/macaroon.v2"
14+
)
15+
16+
type printableToken struct {
17+
ID string `json:"id"`
18+
ValidUntil string `json:"valid_until"`
19+
BaseMacaroon string `json:"base_macaroon"`
20+
PaymentHash string `json:"payment_hash"`
21+
PaymentPreimage string `json:"payment_preimage"`
22+
AmountPaid int64 `json:"amount_paid_msat"`
23+
RoutingFeePaid int64 `json:"routing_fee_paid_msat"`
24+
TimeCreated string `json:"time_created"`
25+
Expired bool `json:"expired"`
26+
FileName string `json:"file_name"`
27+
}
28+
29+
var listAuthCommand = cli.Command{
30+
Name: "listauth",
31+
Usage: "list all LSAT tokens",
32+
Description: "Shows a list of all LSAT tokens that loopd has paid for",
33+
Action: listAuth,
34+
}
35+
36+
func listAuth(ctx *cli.Context) error {
37+
client, cleanup, err := getClient(ctx)
38+
if err != nil {
39+
return err
40+
}
41+
defer cleanup()
42+
43+
resp, err := client.GetLsatTokens(
44+
context.Background(), &looprpc.TokensRequest{},
45+
)
46+
if err != nil {
47+
return err
48+
}
49+
50+
tokens := make([]*printableToken, len(resp.Tokens))
51+
for i, t := range resp.Tokens {
52+
53+
mac := &macaroon.Macaroon{}
54+
err := mac.UnmarshalBinary(t.BaseMacaroon)
55+
if err != nil {
56+
return fmt.Errorf("unable to unmarshal macaroon: %v",
57+
err)
58+
}
59+
id, err := lsat.DecodeIdentifier(bytes.NewReader(mac.Id()))
60+
if err != nil {
61+
return fmt.Errorf("unable to decode macaroon ID: %v",
62+
err)
63+
}
64+
tokens[i] = &printableToken{
65+
ID: hex.EncodeToString(id.TokenID[:]),
66+
ValidUntil: "",
67+
BaseMacaroon: hex.EncodeToString(t.BaseMacaroon),
68+
PaymentHash: hex.EncodeToString(t.PaymentHash),
69+
PaymentPreimage: hex.EncodeToString(t.PaymentPreimage),
70+
AmountPaid: t.AmountPaidMsat,
71+
RoutingFeePaid: t.RoutingFeePaidMsat,
72+
TimeCreated: time.Unix(t.TimeCreated, 0).Format(
73+
time.RFC3339,
74+
),
75+
Expired: t.Expired,
76+
FileName: t.StorageName,
77+
}
78+
}
79+
80+
printJSON(tokens)
81+
return nil
82+
}

cmd/loop/main.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package main
22

33
import (
4+
"bytes"
5+
"encoding/json"
46
"errors"
57
"fmt"
68
"os"
@@ -30,6 +32,21 @@ var (
3032
defaultSwapWaitTime = 30 * time.Minute
3133
)
3234

35+
func printJSON(resp interface{}) {
36+
b, err := json.Marshal(resp)
37+
if err != nil {
38+
fatal(err)
39+
}
40+
41+
var out bytes.Buffer
42+
err = json.Indent(&out, b, "", "\t")
43+
if err != nil {
44+
fatal(err)
45+
}
46+
out.WriteString("\n")
47+
_, _ = out.WriteTo(os.Stdout)
48+
}
49+
3350
func printRespJSON(resp proto.Message) {
3451
jsonMarshaler := &jsonpb.Marshaler{
3552
EmitDefaults: true,
@@ -65,7 +82,7 @@ func main() {
6582
}
6683
app.Commands = []cli.Command{
6784
loopOutCommand, loopInCommand, termsCommand,
68-
monitorCommand, quoteCommand,
85+
monitorCommand, quoteCommand, listAuthCommand,
6986
}
7087

7188
err := app.Run(os.Args)

cmd/loopd/config.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,13 @@ type lndConfig struct {
2727
type viewParameters struct{}
2828

2929
type config struct {
30-
ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"`
31-
Insecure bool `long:"insecure" description:"disable tls"`
32-
Network string `long:"network" description:"network to run on" choice:"regtest" choice:"testnet" choice:"mainnet" choice:"simnet"`
33-
SwapServer string `long:"swapserver" description:"swap server address host:port"`
34-
RPCListen string `long:"rpclisten" description:"Address to listen on for gRPC clients"`
35-
RESTListen string `long:"restlisten" description:"Address to listen on for REST clients"`
30+
ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"`
31+
Insecure bool `long:"insecure" description:"disable tls"`
32+
Network string `long:"network" description:"network to run on" choice:"regtest" choice:"testnet" choice:"mainnet" choice:"simnet"`
33+
SwapServer string `long:"swapserver" description:"swap server address host:port"`
34+
TLSPathSwapSrv string `long:"tlspathswapserver" description:"Path to swap server tls certificate. Only needed if the swap server uses a self-signed certificate."`
35+
RPCListen string `long:"rpclisten" description:"Address to listen on for gRPC clients"`
36+
RESTListen string `long:"restlisten" description:"Address to listen on for REST clients"`
3637

3738
LogDir string `long:"logdir" description:"Directory to log output."`
3839
MaxLogFiles int `long:"maxlogfiles" description:"Maximum logfiles to keep (0 for no rotation)"`

cmd/loopd/daemon.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func daemon(config *config) error {
4545
// Create an instance of the loop client library.
4646
swapClient, cleanup, err := getClient(
4747
config.Network, config.SwapServer, config.Insecure,
48-
&lnd.LndServices,
48+
config.TLSPathSwapSrv, &lnd.LndServices,
4949
)
5050
if err != nil {
5151
return err

cmd/loopd/log.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"github.com/lightninglabs/loop"
66
"github.com/lightninglabs/loop/lndclient"
77
"github.com/lightninglabs/loop/loopdb"
8+
"github.com/lightninglabs/loop/lsat"
89
"github.com/lightningnetwork/lnd/build"
910
)
1011

@@ -19,6 +20,7 @@ func init() {
1920
addSubLogger("LOOP", loop.UseLogger)
2021
addSubLogger("LNDC", lndclient.UseLogger)
2122
addSubLogger("STORE", loopdb.UseLogger)
23+
addSubLogger(lsat.Subsystem, lsat.UseLogger)
2224
}
2325

2426
// addSubLogger is a helper method to conveniently create and register the

cmd/loopd/swapclient_server.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,40 @@ func (s *swapClientServer) LoopIn(ctx context.Context,
346346
}, nil
347347
}
348348

349+
// GetLsatTokens returns all tokens that are contained in the LSAT token store.
350+
func (s *swapClientServer) GetLsatTokens(ctx context.Context,
351+
_ *looprpc.TokensRequest) (*looprpc.TokensResponse, error) {
352+
353+
log.Infof("Get LSAT tokens request received")
354+
355+
tokens, err := s.impl.LsatStore.AllTokens()
356+
if err != nil {
357+
return nil, err
358+
}
359+
360+
rpcTokens := make([]*looprpc.LsatToken, len(tokens))
361+
idx := 0
362+
for key, token := range tokens {
363+
macBytes, err := token.BaseMacaroon().MarshalBinary()
364+
if err != nil {
365+
return nil, err
366+
}
367+
rpcTokens[idx] = &looprpc.LsatToken{
368+
BaseMacaroon: macBytes,
369+
PaymentHash: token.PaymentHash[:],
370+
PaymentPreimage: token.Preimage[:],
371+
AmountPaidMsat: int64(token.AmountPaid),
372+
RoutingFeePaidMsat: int64(token.RoutingFeePaid),
373+
TimeCreated: token.TimeCreated.Unix(),
374+
Expired: !token.IsValid(),
375+
StorageName: key,
376+
}
377+
idx++
378+
}
379+
380+
return &looprpc.TokensResponse{Tokens: rpcTokens}, nil
381+
}
382+
349383
// validateConfTarget ensures the given confirmation target is valid. If one
350384
// isn't specified (0 value), then the default target is used.
351385
func validateConfTarget(target, defaultTarget int32) (int32, error) {

cmd/loopd/utils.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func getLnd(network string, cfg *lndConfig) (*lndclient.GrpcLndServices, error)
1616
}
1717

1818
// getClient returns an instance of the swap client.
19-
func getClient(network, swapServer string, insecure bool,
19+
func getClient(network, swapServer string, insecure bool, tlsPathServer string,
2020
lnd *lndclient.LndServices) (*loop.Client, func(), error) {
2121

2222
storeDir, err := getStoreDir(network)
@@ -25,7 +25,7 @@ func getClient(network, swapServer string, insecure bool,
2525
}
2626

2727
swapClient, cleanUp, err := loop.NewClient(
28-
storeDir, swapServer, insecure, lnd,
28+
storeDir, swapServer, insecure, tlsPathServer, lnd,
2929
)
3030
if err != nil {
3131
return nil, nil, err

cmd/loopd/view.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ func view(config *config) error {
2424
defer lnd.Close()
2525

2626
swapClient, cleanup, err := getClient(
27-
config.Network, config.SwapServer, config.Insecure, &lnd.LndServices,
27+
config.Network, config.SwapServer, config.Insecure,
28+
config.TLSPathSwapSrv, &lnd.LndServices,
2829
)
2930
if err != nil {
3031
return err

config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ import (
55

66
"github.com/lightninglabs/loop/lndclient"
77
"github.com/lightninglabs/loop/loopdb"
8+
"github.com/lightninglabs/loop/lsat"
89
)
910

1011
// clientConfig contains config items for the swap client.
1112
type clientConfig struct {
1213
LndServices *lndclient.LndServices
1314
Server swapServerClient
1415
Store loopdb.SwapStore
16+
LsatStore lsat.Store
1517
CreateExpiryTimer func(expiry time.Duration) <-chan time.Time
1618
}

0 commit comments

Comments
 (0)