config: make total payment timeout and retries configurable

pull/439/head
Andras Banki-Horvath 2 years ago
parent 1943edfd78
commit 1d1354d2cb
No known key found for this signature in database
GPG Key ID: 80E5375C094198D8

@ -108,6 +108,14 @@ type ClientConfig struct {
// for a loop out swap. When greater than one, a multi-part payment may
// be attempted.
LoopOutMaxParts uint32
// TotalPaymentTimeout is the total amount of time until we time out
// off-chain payments (used in loop out).
TotalPaymentTimeout time.Duration
// MaxPaymentRetries is the maximum times we retry an off-chain payment
// (used in loop out).
MaxPaymentRetries int
}
// NewClient returns a new instance to initiate swaps with.
@ -142,12 +150,14 @@ func NewClient(dbDir string, cfg *ClientConfig) (*Client, func(), error) {
}
executor := newExecutor(&executorConfig{
lnd: cfg.Lnd,
store: store,
sweeper: sweeper,
createExpiryTimer: config.CreateExpiryTimer,
loopOutMaxParts: cfg.LoopOutMaxParts,
cancelSwap: swapServerClient.CancelLoopOutSwap,
lnd: cfg.Lnd,
store: store,
sweeper: sweeper,
createExpiryTimer: config.CreateExpiryTimer,
loopOutMaxParts: cfg.LoopOutMaxParts,
totalPaymentTimeout: cfg.TotalPaymentTimeout,
maxPaymentRetries: cfg.MaxPaymentRetries,
cancelSwap: swapServerClient.CancelLoopOutSwap,
})
client := &Client{

@ -26,6 +26,10 @@ type executorConfig struct {
loopOutMaxParts uint32
totalPaymentTimeout time.Duration
maxPaymentRetries int
cancelSwap func(ctx context.Context, details *outCancelDetails) error
}
@ -141,12 +145,14 @@ func (s *executor) run(mainCtx context.Context,
defer s.wg.Done()
err := newSwap.execute(mainCtx, &executeConfig{
statusChan: statusChan,
sweeper: s.sweeper,
blockEpochChan: queue.ChanOut(),
timerFactory: s.executorConfig.createExpiryTimer,
loopOutMaxParts: s.executorConfig.loopOutMaxParts,
cancelSwap: s.executorConfig.cancelSwap,
statusChan: statusChan,
sweeper: s.sweeper,
blockEpochChan: queue.ChanOut(),
timerFactory: s.executorConfig.createExpiryTimer,
loopOutMaxParts: s.executorConfig.loopOutMaxParts,
totalPaymentTimout: s.executorConfig.totalPaymentTimeout,
maxPaymentRetries: s.executorConfig.maxPaymentRetries,
cancelSwap: s.executorConfig.cancelSwap,
}, height)
if err != nil && err != context.Canceled {
log.Errorf("Execute error: %v", err)

@ -33,9 +33,11 @@ var (
LoopDirBase, DefaultNetwork, defaultConfigFilename,
)
defaultMaxLogFiles = 3
defaultMaxLogFileSize = 10
defaultLoopOutMaxParts = uint32(5)
defaultMaxLogFiles = 3
defaultMaxLogFileSize = 10
defaultLoopOutMaxParts = uint32(5)
defaultTotalPaymentTimeout = time.Minute * 60
defaultMaxPaymentRetries = 3
// DefaultTLSCertFilename is the default file name for the autogenerated
// TLS certificate.
@ -144,6 +146,9 @@ type Config struct {
LoopOutMaxParts uint32 `long:"loopoutmaxparts" description:"The maximum number of payment parts that may be used for a loop out swap."`
TotalPaymentTimeout time.Duration `long:"totalpaymenttimeout" description:"The timeout to use for off-chain payments."`
MaxPaymentRetries int `long:"maxpaymentretries" description:"The maximum number of times an off-chain payment may be retried."`
Lnd *lndConfig `group:"lnd" namespace:"lnd"`
Server *loopServerConfig `group:"server" namespace:"server"`
@ -165,19 +170,21 @@ func DefaultConfig() Config {
Server: &loopServerConfig{
NoTLS: false,
},
LoopDir: LoopDirBase,
ConfigFile: defaultConfigFile,
DataDir: LoopDirBase,
LogDir: defaultLogDir,
MaxLogFiles: defaultMaxLogFiles,
MaxLogFileSize: defaultMaxLogFileSize,
DebugLevel: defaultLogLevel,
TLSCertPath: DefaultTLSCertPath,
TLSKeyPath: DefaultTLSKeyPath,
MacaroonPath: DefaultMacaroonPath,
MaxLSATCost: lsat.DefaultMaxCostSats,
MaxLSATFee: lsat.DefaultMaxRoutingFeeSats,
LoopOutMaxParts: defaultLoopOutMaxParts,
LoopDir: LoopDirBase,
ConfigFile: defaultConfigFile,
DataDir: LoopDirBase,
LogDir: defaultLogDir,
MaxLogFiles: defaultMaxLogFiles,
MaxLogFileSize: defaultMaxLogFileSize,
DebugLevel: defaultLogLevel,
TLSCertPath: DefaultTLSCertPath,
TLSKeyPath: DefaultTLSKeyPath,
MacaroonPath: DefaultMacaroonPath,
MaxLSATCost: lsat.DefaultMaxCostSats,
MaxLSATFee: lsat.DefaultMaxRoutingFeeSats,
LoopOutMaxParts: defaultLoopOutMaxParts,
TotalPaymentTimeout: defaultTotalPaymentTimeout,
MaxPaymentRetries: defaultMaxPaymentRetries,
Lnd: &lndConfig{
Host: "localhost:10009",
MacaroonPath: DefaultLndMacaroonPath,
@ -299,6 +306,17 @@ func Validate(cfg *Config) error {
return fmt.Errorf("must specify --lnd.macaroonpath")
}
// Allow at most 2x the default total payment timeout.
if cfg.TotalPaymentTimeout > 2*defaultTotalPaymentTimeout {
return fmt.Errorf("max total payment timeout allowed is at "+
"most %v", 2*defaultTotalPaymentTimeout)
}
// At least one retry.
if cfg.MaxPaymentRetries < 1 {
return fmt.Errorf("max payment retries must be positive")
}
return nil
}

@ -17,14 +17,16 @@ func getClient(config *Config, lnd *lndclient.LndServices) (*loop.Client,
func(), error) {
clientConfig := &loop.ClientConfig{
ServerAddress: config.Server.Host,
ProxyAddress: config.Server.Proxy,
SwapServerNoTLS: config.Server.NoTLS,
TLSPathServer: config.Server.TLSPath,
Lnd: lnd,
MaxLsatCost: btcutil.Amount(config.MaxLSATCost),
MaxLsatFee: btcutil.Amount(config.MaxLSATFee),
LoopOutMaxParts: config.LoopOutMaxParts,
ServerAddress: config.Server.Host,
ProxyAddress: config.Server.Proxy,
SwapServerNoTLS: config.Server.NoTLS,
TLSPathServer: config.Server.TLSPath,
Lnd: lnd,
MaxLsatCost: btcutil.Amount(config.MaxLSATCost),
MaxLsatFee: btcutil.Amount(config.MaxLSATFee),
LoopOutMaxParts: config.LoopOutMaxParts,
TotalPaymentTimeout: config.TotalPaymentTimeout,
MaxPaymentRetries: config.MaxPaymentRetries,
}
swapClient, cleanUp, err := loop.NewClient(config.DataDir, clientConfig)

@ -52,15 +52,6 @@ var (
//
// TODO(wilmer): tune?
DefaultSweepConfTargetDelta = DefaultSweepConfTarget * 2
// totalPaymentTimeout is the total timeout used for the loop out
// offchain payment.
totalPaymentTimeout = time.Minute * 60
// maxPaymentRetries is the maximum number of times the client will
// attempt to pay the invoice before failing the swap. This retry limit
// only applies to when the client uses a routing helper plugin.
maxPaymentRetries = 3
)
// loopOutSwap contains all the in-memory state related to a pending loop out
@ -87,12 +78,14 @@ type loopOutSwap struct {
// executeConfig contains extra configuration to execute the swap.
type executeConfig struct {
sweeper *sweep.Sweeper
statusChan chan<- SwapInfo
blockEpochChan <-chan interface{}
timerFactory func(d time.Duration) <-chan time.Time
loopOutMaxParts uint32
cancelSwap func(context.Context, *outCancelDetails) error
sweeper *sweep.Sweeper
statusChan chan<- SwapInfo
blockEpochChan <-chan interface{}
timerFactory func(d time.Duration) <-chan time.Time
loopOutMaxParts uint32
totalPaymentTimout time.Duration
maxPaymentRetries int
cancelSwap func(context.Context, *outCancelDetails) error
}
// loopOutInitResult contains information about a just-initiated loop out swap.
@ -683,6 +676,8 @@ func (s *loopOutSwap) payInvoiceAsync(ctx context.Context,
}
maxRetries := 1
paymentTimeout := s.executeConfig.totalPaymentTimout
// Attempt to acquire and initialize the routing plugin.
routingPlugin, err := AcquireRoutingPlugin(
ctx, pluginType, *s.lnd, target, nil, amt,
@ -695,11 +690,11 @@ func (s *loopOutSwap) payInvoiceAsync(ctx context.Context,
s.log.Infof("Acquired routing plugin %v for payment %v",
pluginType, hash.String())
maxRetries = maxPaymentRetries
maxRetries = s.executeConfig.maxPaymentRetries
paymentTimeout /= time.Duration(maxRetries)
defer ReleaseRoutingPlugin(ctx)
}
paymentTimeout := totalPaymentTimeout / time.Duration(maxRetries)
req := lndclient.SendPaymentRequest{
MaxFee: maxFee,
Invoice: invoice,

Loading…
Cancel
Save