Skip to content

Commit 4e81f5d

Browse files
committed
challenger: move challenger logic to its own package
The new package contains a new interface (`Challenger`) that any new challenger must implement. Because aperture uses the new interface instead of using directly the `LndChallenger` struct I added the `Stop()` method to the `mint.Challenger`. Instead of also adding the `Start()` method the constructor returns a Challenger already "started".
1 parent a04f3b1 commit 4e81f5d

File tree

7 files changed

+128
-66
lines changed

7 files changed

+128
-66
lines changed

aperture.go

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
flags "github.com/jessevdk/go-flags"
2222
"github.com/lightninglabs/aperture/aperturedb"
2323
"github.com/lightninglabs/aperture/auth"
24+
"github.com/lightninglabs/aperture/challenger"
2425
"github.com/lightninglabs/aperture/mint"
2526
"github.com/lightninglabs/aperture/proxy"
2627
"github.com/lightninglabs/lightning-node-connect/hashmailrpc"
@@ -76,6 +77,10 @@ const (
7677
// hashMailRESTPrefix is the prefix a REST request URI has when it is
7778
// meant for the hashmailrpc server to be handled.
7879
hashMailRESTPrefix = "/v1/lightning-node-connect/hashmail"
80+
81+
// invoiceMacaroonName is the name of the invoice macaroon belonging
82+
// to the target lnd node.
83+
invoiceMacaroonName = "invoice.macaroon"
7984
)
8085

8186
var (
@@ -163,7 +168,7 @@ type Aperture struct {
163168

164169
etcdClient *clientv3.Client
165170
db *sql.DB
166-
challenger *LndChallenger
171+
challenger challenger.Challenger
167172
httpsServer *http.Server
168173
torHTTPServer *http.Server
169174
proxy *proxy.Proxy
@@ -284,37 +289,32 @@ func (a *Aperture) Start(errChan chan error) error {
284289

285290
log.Infof("Using %v as database backend", a.cfg.DatabaseBackend)
286291

287-
// Create our challenger that uses our backing lnd node to create
288-
// invoices and check their settlement status.
289-
genInvoiceReq := func(price int64) (*lnrpc.Invoice, error) {
290-
return &lnrpc.Invoice{
291-
Memo: "LSAT",
292-
Value: price,
293-
}, nil
294-
}
295-
296292
if !a.cfg.Authenticator.Disable {
293+
genInvoiceReq := func(price int64) (*lnrpc.Invoice, error) {
294+
return &lnrpc.Invoice{
295+
Memo: "LSAT",
296+
Value: price,
297+
}, nil
298+
}
299+
297300
authCfg := a.cfg.Authenticator
298301
client, err := lndclient.NewBasicClient(
299-
authCfg.LndHost, authCfg.TLSPath, authCfg.MacDir,
300-
authCfg.Network, lndclient.MacFilename(
302+
authCfg.LndHost, authCfg.TLSPath,
303+
authCfg.MacDir, authCfg.Network,
304+
lndclient.MacFilename(
301305
invoiceMacaroonName,
302306
),
303307
)
304308
if err != nil {
305309
return err
306310
}
307-
308-
a.challenger, err = NewLndChallenger(
309-
client, genInvoiceReq, context.Background, errChan,
311+
a.challenger, err = challenger.NewLndChallenger(
312+
client, genInvoiceReq, context.Background,
313+
errChan,
310314
)
311315
if err != nil {
312316
return err
313317
}
314-
err = a.challenger.Start()
315-
if err != nil {
316-
return err
317-
}
318318
}
319319

320320
// Create the proxy and connect it to lnd.
@@ -750,7 +750,7 @@ func initTorListener(cfg *Config, store tor.OnionStore) (*tor.Controller,
750750
}
751751

752752
// createProxy creates the proxy with all the services it needs.
753-
func createProxy(cfg *Config, challenger *LndChallenger,
753+
func createProxy(cfg *Config, challenger challenger.Challenger,
754754
store mint.SecretStore) (*proxy.Proxy, func(), error) {
755755

756756
minter := mint.New(&mint.Config{

challenger/interface.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package challenger
2+
3+
import (
4+
"context"
5+
6+
"github.com/lightninglabs/aperture/auth"
7+
"github.com/lightninglabs/aperture/mint"
8+
"github.com/lightningnetwork/lnd/lnrpc"
9+
"google.golang.org/grpc"
10+
)
11+
12+
// InvoiceRequestGenerator is a function type that returns a new request for the
13+
// lnrpc.AddInvoice call.
14+
type InvoiceRequestGenerator func(price int64) (*lnrpc.Invoice, error)
15+
16+
// InvoiceClient is an interface that only implements part of a full lnd client,
17+
// namely the part around the invoices we need for the challenger to work.
18+
type InvoiceClient interface {
19+
// ListInvoices returns a paginated list of all invoices known to lnd.
20+
ListInvoices(ctx context.Context, in *lnrpc.ListInvoiceRequest,
21+
opts ...grpc.CallOption) (*lnrpc.ListInvoiceResponse, error)
22+
23+
// SubscribeInvoices subscribes to updates on invoices.
24+
SubscribeInvoices(ctx context.Context, in *lnrpc.InvoiceSubscription,
25+
opts ...grpc.CallOption) (
26+
lnrpc.Lightning_SubscribeInvoicesClient, error)
27+
28+
// AddInvoice adds a new invoice to lnd.
29+
AddInvoice(ctx context.Context, in *lnrpc.Invoice,
30+
opts ...grpc.CallOption) (*lnrpc.AddInvoiceResponse, error)
31+
}
32+
33+
// Challenger is an interface that combines the mint.Challenger and the
34+
// auth.InvoiceChecker interfaces.
35+
type Challenger interface {
36+
mint.Challenger
37+
auth.InvoiceChecker
38+
}

challenger.go renamed to challenger/lnd.go

Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package aperture
1+
package challenger
22

33
import (
44
"context"
@@ -9,34 +9,10 @@ import (
99
"sync"
1010
"time"
1111

12-
"github.com/lightninglabs/aperture/auth"
13-
"github.com/lightninglabs/aperture/mint"
1412
"github.com/lightningnetwork/lnd/lnrpc"
1513
"github.com/lightningnetwork/lnd/lntypes"
16-
"google.golang.org/grpc"
1714
)
1815

19-
// InvoiceRequestGenerator is a function type that returns a new request for the
20-
// lnrpc.AddInvoice call.
21-
type InvoiceRequestGenerator func(price int64) (*lnrpc.Invoice, error)
22-
23-
// InvoiceClient is an interface that only implements part of a full lnd client,
24-
// namely the part around the invoices we need for the challenger to work.
25-
type InvoiceClient interface {
26-
// ListInvoices returns a paginated list of all invoices known to lnd.
27-
ListInvoices(ctx context.Context, in *lnrpc.ListInvoiceRequest,
28-
opts ...grpc.CallOption) (*lnrpc.ListInvoiceResponse, error)
29-
30-
// SubscribeInvoices subscribes to updates on invoices.
31-
SubscribeInvoices(ctx context.Context, in *lnrpc.InvoiceSubscription,
32-
opts ...grpc.CallOption) (
33-
lnrpc.Lightning_SubscribeInvoicesClient, error)
34-
35-
// AddInvoice adds a new invoice to lnd.
36-
AddInvoice(ctx context.Context, in *lnrpc.Invoice,
37-
opts ...grpc.CallOption) (*lnrpc.AddInvoiceResponse, error)
38-
}
39-
4016
// LndChallenger is a challenger that uses an lnd backend to create new LSAT
4117
// payment challenges.
4218
type LndChallenger struct {
@@ -55,16 +31,9 @@ type LndChallenger struct {
5531
wg sync.WaitGroup
5632
}
5733

58-
// A compile time flag to ensure the LndChallenger satisfies the
59-
// mint.Challenger and auth.InvoiceChecker interface.
60-
var _ mint.Challenger = (*LndChallenger)(nil)
61-
var _ auth.InvoiceChecker = (*LndChallenger)(nil)
62-
63-
const (
64-
// invoiceMacaroonName is the name of the invoice macaroon belonging
65-
// to the target lnd node.
66-
invoiceMacaroonName = "invoice.macaroon"
67-
)
34+
// A compile time flag to ensure the LndChallenger satisfies the Challenger
35+
// interface.
36+
var _ Challenger = (*LndChallenger)(nil)
6837

6938
// NewLndChallenger creates a new challenger that uses the given connection to
7039
// an lnd backend to create payment challenges.
@@ -84,7 +53,7 @@ func NewLndChallenger(client InvoiceClient,
8453
}
8554

8655
invoicesMtx := &sync.Mutex{}
87-
return &LndChallenger{
56+
challenger := &LndChallenger{
8857
client: client,
8958
clientCtx: ctxFunc,
9059
genInvoiceReq: genInvoiceReq,
@@ -93,7 +62,14 @@ func NewLndChallenger(client InvoiceClient,
9362
invoicesCond: sync.NewCond(invoicesMtx),
9463
quit: make(chan struct{}),
9564
errChan: errChan,
96-
}, nil
65+
}
66+
67+
err := challenger.Start()
68+
if err != nil {
69+
return nil, fmt.Errorf("unable to start challenger: %w", err)
70+
}
71+
72+
return challenger, nil
9773
}
9874

9975
// Start starts the challenger's main work which is to keep track of all
@@ -263,7 +239,9 @@ func (l *LndChallenger) Stop() {
263239
// request (invoice) and the corresponding payment hash.
264240
//
265241
// NOTE: This is part of the mint.Challenger interface.
266-
func (l *LndChallenger) NewChallenge(price int64) (string, lntypes.Hash, error) {
242+
func (l *LndChallenger) NewChallenge(price int64) (string, lntypes.Hash,
243+
error) {
244+
267245
// Obtain a new invoice from lnd first. We need to know the payment hash
268246
// so we can add it as a caveat to the macaroon.
269247
invoice, err := l.genInvoiceReq(price)

challenger_test.go renamed to challenger/lnd_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package aperture
1+
package challenger
22

33
import (
44
"context"

challenger/log.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package challenger
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 = "CHLL"
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+
}

mint/mint.go

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,24 @@ type Challenger interface {
2929
// to avoid having to decode the payment request in order to retrieve
3030
// its payment hash.
3131
NewChallenge(price int64) (string, lntypes.Hash, error)
32+
33+
// Stop shuts down the challenger.
34+
Stop()
3235
}
3336

3437
// SecretStore is the store responsible for storing LSAT secrets. These secrets
3538
// are required for proper verification of each minted LSAT.
3639
type SecretStore interface {
3740
// NewSecret creates a new cryptographically random secret which is
3841
// keyed by the given hash.
39-
NewSecret(context.Context, [sha256.Size]byte) ([lsat.SecretSize]byte, error)
42+
NewSecret(context.Context, [sha256.Size]byte) ([lsat.SecretSize]byte,
43+
error)
4044

4145
// GetSecret returns the cryptographically random secret that
4246
// corresponds to the given hash. If there is no secret, then
4347
// ErrSecretNotFound is returned.
44-
GetSecret(context.Context, [sha256.Size]byte) ([lsat.SecretSize]byte, error)
48+
GetSecret(context.Context, [sha256.Size]byte) ([lsat.SecretSize]byte,
49+
error)
4550

4651
// RevokeSecret removes the cryptographically random secret that
4752
// corresponds to the given hash. This acts as a NOP if the secret does
@@ -55,16 +60,19 @@ type ServiceLimiter interface {
5560
// ServiceCapabilities returns the capabilities caveats for each
5661
// service. This determines which capabilities of each service can be
5762
// accessed.
58-
ServiceCapabilities(context.Context, ...lsat.Service) ([]lsat.Caveat, error)
63+
ServiceCapabilities(context.Context, ...lsat.Service) ([]lsat.Caveat,
64+
error)
5965

6066
// ServiceConstraints returns the constraints for each service. This
6167
// enforces additional constraints on a particular service/service
6268
// capability.
63-
ServiceConstraints(context.Context, ...lsat.Service) ([]lsat.Caveat, error)
69+
ServiceConstraints(context.Context, ...lsat.Service) ([]lsat.Caveat,
70+
error)
6471

6572
// ServiceTimeouts returns the timeout caveat for each service. This
6673
// will determine if and when service access can expire.
67-
ServiceTimeouts(context.Context, ...lsat.Service) ([]lsat.Caveat, error)
74+
ServiceTimeouts(context.Context, ...lsat.Service) ([]lsat.Caveat,
75+
error)
6876
}
6977

7078
// Config packages all of the required dependencies to instantiate a new LSAT
@@ -245,7 +253,9 @@ type VerificationParams struct {
245253
}
246254

247255
// VerifyLSAT attempts to verify an LSAT with the given parameters.
248-
func (m *Mint) VerifyLSAT(ctx context.Context, params *VerificationParams) error {
256+
func (m *Mint) VerifyLSAT(ctx context.Context,
257+
params *VerificationParams) error {
258+
249259
// We'll first perform a quick check to determine if a valid preimage
250260
// was provided.
251261
id, err := lsat.DecodeIdentifier(bytes.NewReader(params.Macaroon.Id()))

mint/mock_test.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,17 @@ func newMockChallenger() *mockChallenger {
2626
return &mockChallenger{}
2727
}
2828

29-
func (d *mockChallenger) NewChallenge(price int64) (string, lntypes.Hash, error) {
29+
func (d *mockChallenger) Start() error {
30+
return nil
31+
}
32+
33+
func (d *mockChallenger) Stop() {
34+
// Nothing to do here.
35+
}
36+
37+
func (d *mockChallenger) NewChallenge(price int64) (string, lntypes.Hash,
38+
error) {
39+
3040
return testPayReq, testHash, nil
3141
}
3242

0 commit comments

Comments
 (0)