Skip to content

Commit

Permalink
lwk: add backoff for send
Browse files Browse the repository at this point in the history
Send sends a request using the lwkclient and handles retries
 in case of a "missing transaction" error.
It uses an exponential backoff strategy for
retries, with a maximum of 5 retries. This is a temporary workaround
for an issue where a missing transaction
error occurs even when the UTXO exists.
If the issue persists, the backoff strategy may need adjustment.

- Implement retry logic in the `send` function of `lwkclient` using an
  exponential backoff strategy to handle "missing transaction" errors.

fixes: #325
  • Loading branch information
YusukeShimizu committed Oct 31, 2024
1 parent 513f0c6 commit b7070ca
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 9 deletions.
32 changes: 27 additions & 5 deletions lwk/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@ import (
"errors"
"fmt"
"net/http"
"strings"
"time"

"github.com/cenkalti/backoff/v4"
"github.com/elementsproject/glightning/jrpc2"
"github.com/elementsproject/peerswap/log"
)

type lwkclient struct {
Expand Down Expand Up @@ -111,13 +115,31 @@ func (s *sendRequest) Name() string {
return "wallet_send_many"
}

// send sends a request using the lwkclient and handles retries in case of a
// "missing transaction" error. It uses an exponential backoff strategy for
// retries, with a maximum of 5 retries. This is a temporary workaround for
// an issue where a missing transaction error occurs even when the UTXO exists.
// If the issue persists, the backoff strategy may need adjustment.
func (l *lwkclient) send(ctx context.Context, s *sendRequest) (*sendResponse, error) {
var resp sendResponse
err := l.request(ctx, s, &resp)
if err != nil {
return nil, err
}
return &resp, nil
// Allow configuration of maxRetries and backoff strategy
maxRetries := 5
backoffStrategy := backoff.NewExponentialBackOff()
backoffStrategy.MaxElapsedTime = 2 * time.Minute

err := backoff.Retry(func() error {
innerErr := l.request(ctx, s, &resp)
if innerErr != nil {
log.Infof("Error during send request: %v", innerErr)
if strings.Contains(innerErr.Error(), "missing transaction") {
log.Infof("Retrying due to missing transaction error: %v", innerErr)
return innerErr
}
return backoff.Permanent(fmt.Errorf("permanent error: %w", innerErr))
}
return nil
}, backoff.WithMaxRetries(backoffStrategy, uint64(maxRetries)))
return &resp, err
}

type signRequest struct {
Expand Down
9 changes: 5 additions & 4 deletions lwk/lwkwallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package lwk
import (
"context"
"errors"
"fmt"

"math"
"strings"
Expand Down Expand Up @@ -171,25 +172,25 @@ func (r *LWKRpcWallet) CreateAndBroadcastTransaction(swapParams *swap.OpeningPar
FeeRate: &feerate,
})
if err != nil {
return "", "", 0, err
return "", "", 0, fmt.Errorf("failed to fund transaction: %w", err)
}
signed, err := r.lwkClient.sign(ctx, &signRequest{
SignerName: r.c.GetSignerName(),
Pset: fundedTx.Pset,
})
if err != nil {
return "", "", 0, err
return "", "", 0, fmt.Errorf("failed to sign transaction: %w", err)
}
broadcasted, err := r.lwkClient.broadcast(ctx, &broadcastRequest{
WalletName: r.c.GetWalletName(),
Pset: signed.Pset,
})
if err != nil {
return "", "", 0, err
return "", "", 0, fmt.Errorf("failed to broadcast transaction: %w", err)
}
hex, err := r.electrumClient.GetRawTransaction(ctx, broadcasted.Txid)
if err != nil {
return "", "", 0, err
return "", "", 0, fmt.Errorf("failed to get raw transaction: %w", err)
}
return broadcasted.Txid, hex, 0, nil
}
Expand Down

0 comments on commit b7070ca

Please sign in to comment.