mirror of
https://github.com/lightninglabs/aperture.git
synced 2026-02-23 02:14:26 +01:00
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".
This commit is contained in:
40
aperture.go
40
aperture.go
@@ -21,6 +21,7 @@ import (
|
||||
flags "github.com/jessevdk/go-flags"
|
||||
"github.com/lightninglabs/aperture/aperturedb"
|
||||
"github.com/lightninglabs/aperture/auth"
|
||||
"github.com/lightninglabs/aperture/challenger"
|
||||
"github.com/lightninglabs/aperture/mint"
|
||||
"github.com/lightninglabs/aperture/proxy"
|
||||
"github.com/lightninglabs/lightning-node-connect/hashmailrpc"
|
||||
@@ -76,6 +77,10 @@ const (
|
||||
// hashMailRESTPrefix is the prefix a REST request URI has when it is
|
||||
// meant for the hashmailrpc server to be handled.
|
||||
hashMailRESTPrefix = "/v1/lightning-node-connect/hashmail"
|
||||
|
||||
// invoiceMacaroonName is the name of the invoice macaroon belonging
|
||||
// to the target lnd node.
|
||||
invoiceMacaroonName = "invoice.macaroon"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -163,7 +168,7 @@ type Aperture struct {
|
||||
|
||||
etcdClient *clientv3.Client
|
||||
db *sql.DB
|
||||
challenger *LndChallenger
|
||||
challenger challenger.Challenger
|
||||
httpsServer *http.Server
|
||||
torHTTPServer *http.Server
|
||||
proxy *proxy.Proxy
|
||||
@@ -284,37 +289,32 @@ func (a *Aperture) Start(errChan chan error) error {
|
||||
|
||||
log.Infof("Using %v as database backend", a.cfg.DatabaseBackend)
|
||||
|
||||
// Create our challenger that uses our backing lnd node to create
|
||||
// invoices and check their settlement status.
|
||||
genInvoiceReq := func(price int64) (*lnrpc.Invoice, error) {
|
||||
return &lnrpc.Invoice{
|
||||
Memo: "LSAT",
|
||||
Value: price,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if !a.cfg.Authenticator.Disable {
|
||||
genInvoiceReq := func(price int64) (*lnrpc.Invoice, error) {
|
||||
return &lnrpc.Invoice{
|
||||
Memo: "LSAT",
|
||||
Value: price,
|
||||
}, nil
|
||||
}
|
||||
|
||||
authCfg := a.cfg.Authenticator
|
||||
client, err := lndclient.NewBasicClient(
|
||||
authCfg.LndHost, authCfg.TLSPath, authCfg.MacDir,
|
||||
authCfg.Network, lndclient.MacFilename(
|
||||
authCfg.LndHost, authCfg.TLSPath,
|
||||
authCfg.MacDir, authCfg.Network,
|
||||
lndclient.MacFilename(
|
||||
invoiceMacaroonName,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.challenger, err = NewLndChallenger(
|
||||
client, genInvoiceReq, context.Background, errChan,
|
||||
a.challenger, err = challenger.NewLndChallenger(
|
||||
client, genInvoiceReq, context.Background,
|
||||
errChan,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = a.challenger.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Create the proxy and connect it to lnd.
|
||||
@@ -750,7 +750,7 @@ func initTorListener(cfg *Config, store tor.OnionStore) (*tor.Controller,
|
||||
}
|
||||
|
||||
// createProxy creates the proxy with all the services it needs.
|
||||
func createProxy(cfg *Config, challenger *LndChallenger,
|
||||
func createProxy(cfg *Config, challenger challenger.Challenger,
|
||||
store mint.SecretStore) (*proxy.Proxy, func(), error) {
|
||||
|
||||
minter := mint.New(&mint.Config{
|
||||
|
||||
38
challenger/interface.go
Normal file
38
challenger/interface.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package challenger
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/lightninglabs/aperture/auth"
|
||||
"github.com/lightninglabs/aperture/mint"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// InvoiceRequestGenerator is a function type that returns a new request for the
|
||||
// lnrpc.AddInvoice call.
|
||||
type InvoiceRequestGenerator func(price int64) (*lnrpc.Invoice, error)
|
||||
|
||||
// InvoiceClient is an interface that only implements part of a full lnd client,
|
||||
// namely the part around the invoices we need for the challenger to work.
|
||||
type InvoiceClient interface {
|
||||
// ListInvoices returns a paginated list of all invoices known to lnd.
|
||||
ListInvoices(ctx context.Context, in *lnrpc.ListInvoiceRequest,
|
||||
opts ...grpc.CallOption) (*lnrpc.ListInvoiceResponse, error)
|
||||
|
||||
// SubscribeInvoices subscribes to updates on invoices.
|
||||
SubscribeInvoices(ctx context.Context, in *lnrpc.InvoiceSubscription,
|
||||
opts ...grpc.CallOption) (
|
||||
lnrpc.Lightning_SubscribeInvoicesClient, error)
|
||||
|
||||
// AddInvoice adds a new invoice to lnd.
|
||||
AddInvoice(ctx context.Context, in *lnrpc.Invoice,
|
||||
opts ...grpc.CallOption) (*lnrpc.AddInvoiceResponse, error)
|
||||
}
|
||||
|
||||
// Challenger is an interface that combines the mint.Challenger and the
|
||||
// auth.InvoiceChecker interfaces.
|
||||
type Challenger interface {
|
||||
mint.Challenger
|
||||
auth.InvoiceChecker
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package aperture
|
||||
package challenger
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -9,34 +9,10 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/lightninglabs/aperture/auth"
|
||||
"github.com/lightninglabs/aperture/mint"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// InvoiceRequestGenerator is a function type that returns a new request for the
|
||||
// lnrpc.AddInvoice call.
|
||||
type InvoiceRequestGenerator func(price int64) (*lnrpc.Invoice, error)
|
||||
|
||||
// InvoiceClient is an interface that only implements part of a full lnd client,
|
||||
// namely the part around the invoices we need for the challenger to work.
|
||||
type InvoiceClient interface {
|
||||
// ListInvoices returns a paginated list of all invoices known to lnd.
|
||||
ListInvoices(ctx context.Context, in *lnrpc.ListInvoiceRequest,
|
||||
opts ...grpc.CallOption) (*lnrpc.ListInvoiceResponse, error)
|
||||
|
||||
// SubscribeInvoices subscribes to updates on invoices.
|
||||
SubscribeInvoices(ctx context.Context, in *lnrpc.InvoiceSubscription,
|
||||
opts ...grpc.CallOption) (
|
||||
lnrpc.Lightning_SubscribeInvoicesClient, error)
|
||||
|
||||
// AddInvoice adds a new invoice to lnd.
|
||||
AddInvoice(ctx context.Context, in *lnrpc.Invoice,
|
||||
opts ...grpc.CallOption) (*lnrpc.AddInvoiceResponse, error)
|
||||
}
|
||||
|
||||
// LndChallenger is a challenger that uses an lnd backend to create new LSAT
|
||||
// payment challenges.
|
||||
type LndChallenger struct {
|
||||
@@ -55,16 +31,9 @@ type LndChallenger struct {
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
// A compile time flag to ensure the LndChallenger satisfies the
|
||||
// mint.Challenger and auth.InvoiceChecker interface.
|
||||
var _ mint.Challenger = (*LndChallenger)(nil)
|
||||
var _ auth.InvoiceChecker = (*LndChallenger)(nil)
|
||||
|
||||
const (
|
||||
// invoiceMacaroonName is the name of the invoice macaroon belonging
|
||||
// to the target lnd node.
|
||||
invoiceMacaroonName = "invoice.macaroon"
|
||||
)
|
||||
// A compile time flag to ensure the LndChallenger satisfies the Challenger
|
||||
// interface.
|
||||
var _ Challenger = (*LndChallenger)(nil)
|
||||
|
||||
// NewLndChallenger creates a new challenger that uses the given connection to
|
||||
// an lnd backend to create payment challenges.
|
||||
@@ -84,7 +53,7 @@ func NewLndChallenger(client InvoiceClient,
|
||||
}
|
||||
|
||||
invoicesMtx := &sync.Mutex{}
|
||||
return &LndChallenger{
|
||||
challenger := &LndChallenger{
|
||||
client: client,
|
||||
clientCtx: ctxFunc,
|
||||
genInvoiceReq: genInvoiceReq,
|
||||
@@ -93,7 +62,14 @@ func NewLndChallenger(client InvoiceClient,
|
||||
invoicesCond: sync.NewCond(invoicesMtx),
|
||||
quit: make(chan struct{}),
|
||||
errChan: errChan,
|
||||
}, nil
|
||||
}
|
||||
|
||||
err := challenger.Start()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to start challenger: %w", err)
|
||||
}
|
||||
|
||||
return challenger, nil
|
||||
}
|
||||
|
||||
// Start starts the challenger's main work which is to keep track of all
|
||||
@@ -263,7 +239,9 @@ func (l *LndChallenger) Stop() {
|
||||
// request (invoice) and the corresponding payment hash.
|
||||
//
|
||||
// NOTE: This is part of the mint.Challenger interface.
|
||||
func (l *LndChallenger) NewChallenge(price int64) (string, lntypes.Hash, error) {
|
||||
func (l *LndChallenger) NewChallenge(price int64) (string, lntypes.Hash,
|
||||
error) {
|
||||
|
||||
// Obtain a new invoice from lnd first. We need to know the payment hash
|
||||
// so we can add it as a caveat to the macaroon.
|
||||
invoice, err := l.genInvoiceReq(price)
|
||||
@@ -1,4 +1,4 @@
|
||||
package aperture
|
||||
package challenger
|
||||
|
||||
import (
|
||||
"context"
|
||||
26
challenger/log.go
Normal file
26
challenger/log.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package challenger
|
||||
|
||||
import (
|
||||
"github.com/btcsuite/btclog"
|
||||
"github.com/lightningnetwork/lnd/build"
|
||||
)
|
||||
|
||||
// Subsystem defines the sub system name of this package.
|
||||
const Subsystem = "CHLL"
|
||||
|
||||
// log is a logger that is initialized with no output filters. This
|
||||
// means the package will not perform any logging by default until the caller
|
||||
// requests it.
|
||||
var log btclog.Logger
|
||||
|
||||
// The default amount of logging is none.
|
||||
func init() {
|
||||
UseLogger(build.NewSubLogger(Subsystem, nil))
|
||||
}
|
||||
|
||||
// UseLogger uses a specified Logger to output package logging info.
|
||||
// This should be used in preference to SetLogWriter if the caller is also
|
||||
// using btclog.
|
||||
func UseLogger(logger btclog.Logger) {
|
||||
log = logger
|
||||
}
|
||||
22
mint/mint.go
22
mint/mint.go
@@ -29,6 +29,9 @@ type Challenger interface {
|
||||
// to avoid having to decode the payment request in order to retrieve
|
||||
// its payment hash.
|
||||
NewChallenge(price int64) (string, lntypes.Hash, error)
|
||||
|
||||
// Stop shuts down the challenger.
|
||||
Stop()
|
||||
}
|
||||
|
||||
// SecretStore is the store responsible for storing LSAT secrets. These secrets
|
||||
@@ -36,12 +39,14 @@ type Challenger interface {
|
||||
type SecretStore interface {
|
||||
// NewSecret creates a new cryptographically random secret which is
|
||||
// keyed by the given hash.
|
||||
NewSecret(context.Context, [sha256.Size]byte) ([lsat.SecretSize]byte, error)
|
||||
NewSecret(context.Context, [sha256.Size]byte) ([lsat.SecretSize]byte,
|
||||
error)
|
||||
|
||||
// GetSecret returns the cryptographically random secret that
|
||||
// corresponds to the given hash. If there is no secret, then
|
||||
// ErrSecretNotFound is returned.
|
||||
GetSecret(context.Context, [sha256.Size]byte) ([lsat.SecretSize]byte, error)
|
||||
GetSecret(context.Context, [sha256.Size]byte) ([lsat.SecretSize]byte,
|
||||
error)
|
||||
|
||||
// RevokeSecret removes the cryptographically random secret that
|
||||
// corresponds to the given hash. This acts as a NOP if the secret does
|
||||
@@ -55,16 +60,19 @@ type ServiceLimiter interface {
|
||||
// ServiceCapabilities returns the capabilities caveats for each
|
||||
// service. This determines which capabilities of each service can be
|
||||
// accessed.
|
||||
ServiceCapabilities(context.Context, ...lsat.Service) ([]lsat.Caveat, error)
|
||||
ServiceCapabilities(context.Context, ...lsat.Service) ([]lsat.Caveat,
|
||||
error)
|
||||
|
||||
// ServiceConstraints returns the constraints for each service. This
|
||||
// enforces additional constraints on a particular service/service
|
||||
// capability.
|
||||
ServiceConstraints(context.Context, ...lsat.Service) ([]lsat.Caveat, error)
|
||||
ServiceConstraints(context.Context, ...lsat.Service) ([]lsat.Caveat,
|
||||
error)
|
||||
|
||||
// ServiceTimeouts returns the timeout caveat for each service. This
|
||||
// will determine if and when service access can expire.
|
||||
ServiceTimeouts(context.Context, ...lsat.Service) ([]lsat.Caveat, error)
|
||||
ServiceTimeouts(context.Context, ...lsat.Service) ([]lsat.Caveat,
|
||||
error)
|
||||
}
|
||||
|
||||
// Config packages all of the required dependencies to instantiate a new LSAT
|
||||
@@ -245,7 +253,9 @@ type VerificationParams struct {
|
||||
}
|
||||
|
||||
// VerifyLSAT attempts to verify an LSAT with the given parameters.
|
||||
func (m *Mint) VerifyLSAT(ctx context.Context, params *VerificationParams) error {
|
||||
func (m *Mint) VerifyLSAT(ctx context.Context,
|
||||
params *VerificationParams) error {
|
||||
|
||||
// We'll first perform a quick check to determine if a valid preimage
|
||||
// was provided.
|
||||
id, err := lsat.DecodeIdentifier(bytes.NewReader(params.Macaroon.Id()))
|
||||
|
||||
@@ -26,7 +26,17 @@ func newMockChallenger() *mockChallenger {
|
||||
return &mockChallenger{}
|
||||
}
|
||||
|
||||
func (d *mockChallenger) NewChallenge(price int64) (string, lntypes.Hash, error) {
|
||||
func (d *mockChallenger) Start() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *mockChallenger) Stop() {
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
func (d *mockChallenger) NewChallenge(price int64) (string, lntypes.Hash,
|
||||
error) {
|
||||
|
||||
return testPayReq, testHash, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user