|
|
@ -8,6 +8,7 @@ import (
|
|
|
|
"sync"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/btcsuite/btcutil"
|
|
|
|
"github.com/lightninglabs/loop/lndclient"
|
|
|
|
"github.com/lightninglabs/loop/lndclient"
|
|
|
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
|
|
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
|
|
|
"github.com/lightningnetwork/lnd/lnwire"
|
|
|
|
"github.com/lightningnetwork/lnd/lnwire"
|
|
|
@ -67,6 +68,8 @@ type Interceptor struct {
|
|
|
|
lnd *lndclient.LndServices
|
|
|
|
lnd *lndclient.LndServices
|
|
|
|
store Store
|
|
|
|
store Store
|
|
|
|
callTimeout time.Duration
|
|
|
|
callTimeout time.Duration
|
|
|
|
|
|
|
|
maxCost btcutil.Amount
|
|
|
|
|
|
|
|
maxFee btcutil.Amount
|
|
|
|
lock sync.Mutex
|
|
|
|
lock sync.Mutex
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -74,12 +77,15 @@ type Interceptor struct {
|
|
|
|
// lnd connection to automatically acquire and pay for LSAT tokens, unless the
|
|
|
|
// lnd connection to automatically acquire and pay for LSAT tokens, unless the
|
|
|
|
// indicated store already contains a usable token.
|
|
|
|
// indicated store already contains a usable token.
|
|
|
|
func NewInterceptor(lnd *lndclient.LndServices, store Store,
|
|
|
|
func NewInterceptor(lnd *lndclient.LndServices, store Store,
|
|
|
|
rpcCallTimeout time.Duration) *Interceptor {
|
|
|
|
rpcCallTimeout time.Duration, maxCost,
|
|
|
|
|
|
|
|
maxFee btcutil.Amount) *Interceptor {
|
|
|
|
|
|
|
|
|
|
|
|
return &Interceptor{
|
|
|
|
return &Interceptor{
|
|
|
|
lnd: lnd,
|
|
|
|
lnd: lnd,
|
|
|
|
store: store,
|
|
|
|
store: store,
|
|
|
|
callTimeout: rpcCallTimeout,
|
|
|
|
callTimeout: rpcCallTimeout,
|
|
|
|
|
|
|
|
maxCost: maxCost,
|
|
|
|
|
|
|
|
maxFee: maxFee,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -226,6 +232,14 @@ func (i *Interceptor) payLsatToken(ctx context.Context, md *metadata.MD) (
|
|
|
|
return nil, fmt.Errorf("unable to decode invoice: %v", err)
|
|
|
|
return nil, fmt.Errorf("unable to decode invoice: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check that the charged amount does not exceed our maximum cost.
|
|
|
|
|
|
|
|
maxCostMsat := lnwire.NewMSatFromSatoshis(i.maxCost)
|
|
|
|
|
|
|
|
if invoice.MilliSat != nil && *invoice.MilliSat > maxCostMsat {
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("cannot pay for LSAT automatically, "+
|
|
|
|
|
|
|
|
"cost of %d msat exceeds configured max cost of %d "+
|
|
|
|
|
|
|
|
"msat", *invoice.MilliSat, maxCostMsat)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Create and store the pending token so we can resume the payment in
|
|
|
|
// Create and store the pending token so we can resume the payment in
|
|
|
|
// case the payment is interrupted somehow.
|
|
|
|
// case the payment is interrupted somehow.
|
|
|
|
token, err := tokenFromChallenge(macBytes, invoice.PaymentHash)
|
|
|
|
token, err := tokenFromChallenge(macBytes, invoice.PaymentHash)
|
|
|
@ -242,7 +256,7 @@ func (i *Interceptor) payLsatToken(ctx context.Context, md *metadata.MD) (
|
|
|
|
payCtx, cancel := context.WithTimeout(ctx, PaymentTimeout)
|
|
|
|
payCtx, cancel := context.WithTimeout(ctx, PaymentTimeout)
|
|
|
|
defer cancel()
|
|
|
|
defer cancel()
|
|
|
|
respChan := i.lnd.Client.PayInvoice(
|
|
|
|
respChan := i.lnd.Client.PayInvoice(
|
|
|
|
payCtx, invoiceStr, DefaultMaxRoutingFeeSats, nil,
|
|
|
|
payCtx, invoiceStr, i.maxFee, nil,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
select {
|
|
|
|
select {
|
|
|
|
case result := <-respChan:
|
|
|
|
case result := <-respChan:
|
|
|
|