Skip to content

Commit da41dd9

Browse files
committed
interceptor: move client interceptor to its own package
1 parent c34f0d2 commit da41dd9

File tree

9 files changed

+114
-68
lines changed

9 files changed

+114
-68
lines changed

lsat/client_interceptor.go renamed to interceptor/client_interceptor.go

+18-15
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package lsat
1+
package interceptor
22

33
import (
44
"context"
@@ -11,6 +11,7 @@ import (
1111
"time"
1212

1313
"github.com/btcsuite/btcd/btcutil"
14+
"github.com/lightninglabs/aperture/lsat"
1415
"github.com/lightninglabs/lndclient"
1516
"github.com/lightningnetwork/lnd/lnrpc"
1617
"github.com/lightningnetwork/lnd/lnwire"
@@ -77,18 +78,18 @@ var (
7778
// connection to lnd to automatically pay for an authentication token.
7879
type ClientInterceptor struct {
7980
lnd *lndclient.LndServices
80-
store Store
81+
store lsat.Store
8182
callTimeout time.Duration
8283
maxCost btcutil.Amount
8384
maxFee btcutil.Amount
8485
lock sync.Mutex
8586
allowInsecure bool
8687
}
8788

88-
// NewInterceptor creates a new gRPC client interceptor that uses the provided
89-
// lnd connection to automatically acquire and pay for LSAT tokens, unless the
90-
// indicated store already contains a usable token.
91-
func NewInterceptor(lnd *lndclient.LndServices, store Store,
89+
// NewClientInterceptor creates a new gRPC client interceptor that uses the
90+
// provided lnd connection to automatically acquire and pay for LSAT tokens,
91+
// unless the indicated store already contains a usable token.
92+
func NewClientInterceptor(lnd *lndclient.LndServices, store lsat.Store,
9293
rpcCallTimeout time.Duration, maxCost,
9394
maxFee btcutil.Amount, allowInsecure bool) *ClientInterceptor {
9495

@@ -108,7 +109,7 @@ type interceptContext struct {
108109
mainCtx context.Context
109110
opts []grpc.CallOption
110111
metadata *metadata.MD
111-
token *Token
112+
token *lsat.Token
112113
}
113114

114115
// UnaryInterceptor is an interceptor method that can be used directly by gRPC
@@ -223,7 +224,7 @@ func (i *ClientInterceptor) newInterceptContext(ctx context.Context,
223224
iCtx.token, err = i.store.CurrentToken()
224225
switch {
225226
// If there is no token yet, nothing to do at this point.
226-
case err == ErrNoToken:
227+
case err == lsat.ErrNoToken:
227228

228229
// Some other error happened that we have to surface.
229230
case err != nil:
@@ -235,7 +236,7 @@ func (i *ClientInterceptor) newInterceptContext(ctx context.Context,
235236
// payment just yet, since we don't even know if a token is required for
236237
// this call. We also never send a pending payment to the server since
237238
// we know it's not valid.
238-
case !iCtx.token.isPending():
239+
case !iCtx.token.IsPending():
239240
if err = i.addLsatCredentials(iCtx); err != nil {
240241
log.Errorf("Adding macaroon to request failed: %v", err)
241242
return nil, fmt.Errorf("adding macaroon failed: %v",
@@ -257,7 +258,7 @@ func (i *ClientInterceptor) newInterceptContext(ctx context.Context,
257258
func (i *ClientInterceptor) handlePayment(iCtx *interceptContext) error {
258259
switch {
259260
// Resume/track a pending payment if it was interrupted for some reason.
260-
case iCtx.token != nil && iCtx.token.isPending():
261+
case iCtx.token != nil && iCtx.token.IsPending():
261262
log.Infof("Payment of LSAT token is required, resuming/" +
262263
"tracking previous payment from pending LSAT token")
263264
err := i.trackPayment(iCtx.mainCtx, iCtx.token)
@@ -321,7 +322,7 @@ func (i *ClientInterceptor) addLsatCredentials(iCtx *interceptContext) error {
321322
return err
322323
}
323324
iCtx.opts = append(iCtx.opts, grpc.PerRPCCredentials(
324-
NewMacaroonCredential(macaroon, i.allowInsecure),
325+
lsat.NewMacaroonCredential(macaroon, i.allowInsecure),
325326
))
326327
return nil
327328
}
@@ -330,7 +331,7 @@ func (i *ClientInterceptor) addLsatCredentials(iCtx *interceptContext) error {
330331
// to pay the invoice encoded in them, returning a paid LSAT token if
331332
// successful.
332333
func (i *ClientInterceptor) payLsatToken(ctx context.Context, md *metadata.MD) (
333-
*Token, error) {
334+
*lsat.Token, error) {
334335

335336
// First parse the authentication header that was stored in the
336337
// metadata.
@@ -367,7 +368,7 @@ func (i *ClientInterceptor) payLsatToken(ctx context.Context, md *metadata.MD) (
367368

368369
// Create and store the pending token so we can resume the payment in
369370
// case the payment is interrupted somehow.
370-
token, err := tokenFromChallenge(macBytes, invoice.PaymentHash)
371+
token, err := lsat.TokenFromChallenge(macBytes, invoice.PaymentHash)
371372
if err != nil {
372373
return nil, fmt.Errorf("unable to create token: %v", err)
373374
}
@@ -407,7 +408,9 @@ func (i *ClientInterceptor) payLsatToken(ctx context.Context, md *metadata.MD) (
407408

408409
// trackPayment tries to resume a pending payment by tracking its state and
409410
// waiting for a conclusive result.
410-
func (i *ClientInterceptor) trackPayment(ctx context.Context, token *Token) error {
411+
func (i *ClientInterceptor) trackPayment(ctx context.Context,
412+
token *lsat.Token) error {
413+
411414
// Lookup state of the payment.
412415
paymentStateCtx, cancel := context.WithCancel(ctx)
413416
defer cancel()
@@ -486,7 +489,7 @@ func IsPaymentRequired(err error) bool {
486489

487490
// extractPaymentDetails extracts the preimage and amounts paid for a payment
488491
// from the payment status and stores them in the token.
489-
func extractPaymentDetails(token *Token, status lndclient.PaymentStatus) {
492+
func extractPaymentDetails(token *lsat.Token, status lndclient.PaymentStatus) {
490493
token.Preimage = status.Preimage
491494
token.AmountPaid = status.Value
492495
token.RoutingFeePaid = status.Fee

lsat/client_interceptor_test.go renamed to interceptor/client_interceptor_test.go

+17-27
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package lsat
1+
package interceptor
22

33
import (
44
"context"
@@ -10,6 +10,7 @@ import (
1010
"time"
1111

1212
"github.com/lightninglabs/aperture/internal/test"
13+
"github.com/lightninglabs/aperture/lsat"
1314
"github.com/lightninglabs/lndclient"
1415
"github.com/lightningnetwork/lnd/lnrpc"
1516
"github.com/lightningnetwork/lnd/lntypes"
@@ -36,21 +37,21 @@ type interceptTestCase struct {
3637
}
3738

3839
type mockStore struct {
39-
token *Token
40+
token *lsat.Token
4041
}
4142

42-
func (s *mockStore) CurrentToken() (*Token, error) {
43+
func (s *mockStore) CurrentToken() (*lsat.Token, error) {
4344
if s.token == nil {
44-
return nil, ErrNoToken
45+
return nil, lsat.ErrNoToken
4546
}
4647
return s.token, nil
4748
}
4849

49-
func (s *mockStore) AllTokens() (map[string]*Token, error) {
50-
return map[string]*Token{"foo": s.token}, nil
50+
func (s *mockStore) AllTokens() (map[string]*lsat.Token, error) {
51+
return map[string]*lsat.Token{"foo": s.token}, nil
5152
}
5253

53-
func (s *mockStore) StoreToken(token *Token) error {
54+
func (s *mockStore) StoreToken(token *lsat.Token) error {
5455
s.token = token
5556
return nil
5657
}
@@ -64,11 +65,11 @@ var (
6465
lnd = test.NewMockLnd()
6566
store = &mockStore{}
6667
testTimeout = 5 * time.Second
67-
interceptor = NewInterceptor(
68+
interceptor = NewClientInterceptor(
6869
&lnd.LndServices, store, testTimeout,
6970
DefaultMaxCostSats, DefaultMaxRoutingFeeSats, false,
7071
)
71-
testMac = makeMac()
72+
testMac = lsat.MakeMac()
7273
testMacBytes = serializeMac(testMac)
7374
testMacHex = hex.EncodeToString(testMacBytes)
7475
paidPreimage = lntypes.Preimage{1, 2, 3, 4, 5}
@@ -135,7 +136,7 @@ var (
135136
expectMacaroonCall2: false,
136137
}, {
137138
name: "auth required, has pending token",
138-
initialPreimage: &zeroPreimage,
139+
initialPreimage: &lsat.ZeroPreimage,
139140
interceptor: interceptor,
140141
resetCb: func() {
141142
resetBackend(
@@ -166,7 +167,7 @@ var (
166167
expectMacaroonCall2: true,
167168
}, {
168169
name: "auth required, has pending but expired token",
169-
initialPreimage: &zeroPreimage,
170+
initialPreimage: &lsat.ZeroPreimage,
170171
interceptor: interceptor,
171172
resetCb: func() {
172173
resetBackend(
@@ -207,7 +208,7 @@ var (
207208
}, {
208209
name: "auth required, no token yet, cost limit",
209210
initialPreimage: nil,
210-
interceptor: NewInterceptor(
211+
interceptor: NewClientInterceptor(
211212
&lnd.LndServices, store, testTimeout, 100,
212213
DefaultMaxRoutingFeeSats, false,
213214
),
@@ -393,7 +394,7 @@ func testInterceptor(t *testing.T, tc interceptTestCase,
393394
require.NoError(t, err)
394395
require.Equal(t, paidPreimage, storeToken.Preimage)
395396
} else {
396-
require.Equal(t, ErrNoToken, err)
397+
require.Equal(t, lsat.ErrNoToken, err)
397398
}
398399
if tc.expectMacaroonCall2 {
399400
require.Len(t, callMD, 1)
@@ -405,27 +406,16 @@ func testInterceptor(t *testing.T, tc interceptTestCase,
405406
require.Equal(t, tc.expectBackendCalls, numBackendCalls)
406407
}
407408

408-
func makeToken(preimage *lntypes.Preimage) *Token {
409+
func makeToken(preimage *lntypes.Preimage) *lsat.Token {
409410
if preimage == nil {
410411
return nil
411412
}
412-
return &Token{
413+
return &lsat.Token{
413414
Preimage: *preimage,
414-
baseMac: testMac,
415+
BaseMac: testMac,
415416
}
416417
}
417418

418-
func makeMac() *macaroon.Macaroon {
419-
dummyMac, err := macaroon.New(
420-
[]byte("aabbccddeeff00112233445566778899"), []byte("AA=="),
421-
"LSAT", macaroon.LatestVersion,
422-
)
423-
if err != nil {
424-
panic(fmt.Errorf("unable to create macaroon: %v", err))
425-
}
426-
return dummyMac
427-
}
428-
429419
func serializeMac(mac *macaroon.Macaroon) []byte {
430420
macBytes, err := mac.MarshalBinary()
431421
if err != nil {

interceptor/log.go

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package interceptor
2+
3+
import (
4+
"github.com/btcsuite/btclog"
5+
"github.com/lightningnetwork/lnd/build"
6+
)
7+
8+
// Subsystem defines the sub system name of this package.
9+
const Subsystem = "INPR"
10+
11+
// log is a logger that is initialized with no output filters. This
12+
// means the package will not perform any logging by default until the caller
13+
// requests it.
14+
var log btclog.Logger
15+
16+
// The default amount of logging is none.
17+
func init() {
18+
UseLogger(build.NewSubLogger(Subsystem, nil))
19+
}
20+
21+
// UseLogger uses a specified Logger to output package logging info.
22+
// This should be used in preference to SetLogWriter if the caller is also
23+
// using btclog.
24+
func UseLogger(logger btclog.Logger) {
25+
log = logger
26+
}

log.go

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"github.com/btcsuite/btclog"
55
"github.com/lightninglabs/aperture/auth"
66
"github.com/lightninglabs/aperture/challenger"
7+
"github.com/lightninglabs/aperture/interceptor"
78
"github.com/lightninglabs/aperture/lsat"
89
"github.com/lightninglabs/aperture/proxy"
910
"github.com/lightninglabs/lndclient"
@@ -31,6 +32,9 @@ func SetupLoggers(root *build.RotatingLogWriter, intercept signal.Interceptor) {
3132
lnd.AddSubLogger(
3233
root, challenger.Subsystem, intercept, challenger.UseLogger,
3334
)
35+
lnd.AddSubLogger(
36+
root, interceptor.Subsystem, intercept, interceptor.UseLogger,
37+
)
3438
lnd.AddSubLogger(root, lsat.Subsystem, intercept, lsat.UseLogger)
3539
lnd.AddSubLogger(root, proxy.Subsystem, intercept, proxy.UseLogger)
3640
lnd.AddSubLogger(root, "LNDC", intercept, lndclient.UseLogger)

lsat/store.go

+8-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,12 @@ var (
2424
// errNoReplace is the error that is returned if a new token is
2525
// being written to a store that already contains a paid token.
2626
errNoReplace = errors.New("won't replace existing paid token with " +
27-
"new token. " + manualRetryHint)
27+
"new token. " + ManualRetryHint)
28+
29+
// ManualRetryHint is the error text we return to tell the user how a
30+
// token payment can be retried if the payment fails.
31+
ManualRetryHint = "consider removing pending token file if error " +
32+
"persists. use 'listauth' command to find out token file name"
2833
)
2934

3035
// Store is an interface that allows users to store and retrieve an LSAT token.
@@ -152,7 +157,7 @@ func (f *FileStore) StoreToken(newToken *Token) error {
152157
case err == ErrNoToken:
153158
// What's the target file name we are going to write?
154159
newFileName := f.fileName
155-
if newToken.isPending() {
160+
if newToken.IsPending() {
156161
newFileName = f.fileNamePending
157162
}
158163
return os.WriteFile(newFileName, bytes, 0600)
@@ -162,7 +167,7 @@ func (f *FileStore) StoreToken(newToken *Token) error {
162167
return err
163168

164169
// Replace a pending token with a paid one.
165-
case currentToken.isPending() && !newToken.isPending():
170+
case currentToken.IsPending() && !newToken.IsPending():
166171
// Make sure we replace the the same token, just with a
167172
// different state.
168173
if currentToken.PaymentHash != newToken.PaymentHash {

lsat/store_test.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ func TestFileStore(t *testing.T) {
2222
paidPreimage = lntypes.Preimage{1, 2, 3, 4, 5}
2323
paidToken = &Token{
2424
Preimage: paidPreimage,
25-
baseMac: makeMac(),
25+
BaseMac: MakeMac(),
2626
}
2727
pendingToken = &Token{
28-
Preimage: zeroPreimage,
29-
baseMac: makeMac(),
28+
Preimage: ZeroPreimage,
29+
BaseMac: MakeMac(),
3030
}
3131
)
3232

@@ -61,7 +61,7 @@ func TestFileStore(t *testing.T) {
6161
if err != nil {
6262
t.Fatalf("could not read pending token: %v", err)
6363
}
64-
if !token.baseMac.Equal(pendingToken.baseMac) {
64+
if !token.BaseMac.Equal(pendingToken.BaseMac) {
6565
t.Fatalf("expected macaroon to match")
6666
}
6767
tokens, err = store.AllTokens()
@@ -73,7 +73,7 @@ func TestFileStore(t *testing.T) {
7373
len(tokens), 1)
7474
}
7575
for key := range tokens {
76-
if !tokens[key].baseMac.Equal(pendingToken.baseMac) {
76+
if !tokens[key].BaseMac.Equal(pendingToken.BaseMac) {
7777
t.Fatalf("expected macaroon to match")
7878
}
7979
}
@@ -96,7 +96,7 @@ func TestFileStore(t *testing.T) {
9696
if err != nil {
9797
t.Fatalf("could not read pending token: %v", err)
9898
}
99-
if !token.baseMac.Equal(paidToken.baseMac) {
99+
if !token.BaseMac.Equal(paidToken.BaseMac) {
100100
t.Fatalf("expected macaroon to match")
101101
}
102102
tokens, err = store.AllTokens()
@@ -108,7 +108,7 @@ func TestFileStore(t *testing.T) {
108108
len(tokens), 1)
109109
}
110110
for key := range tokens {
111-
if !tokens[key].baseMac.Equal(paidToken.baseMac) {
111+
if !tokens[key].BaseMac.Equal(paidToken.BaseMac) {
112112
t.Fatalf("expected macaroon to match")
113113
}
114114
}

lsat/test_utils.go

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package lsat
2+
3+
import (
4+
"fmt"
5+
6+
"gopkg.in/macaroon.v2"
7+
)
8+
9+
func MakeMac() *macaroon.Macaroon {
10+
dummyMac, err := macaroon.New(
11+
[]byte("aabbccddeeff00112233445566778899"), []byte("AA=="),
12+
"LSAT", macaroon.LatestVersion,
13+
)
14+
if err != nil {
15+
panic(fmt.Errorf("unable to create macaroon: %v", err))
16+
}
17+
return dummyMac
18+
}

0 commit comments

Comments
 (0)