instantout/reservation: extend RPC state wait timeout

RequestReservationFromServer blocked for defaultWaitForStateTime (15s)
waiting for the FSM to reach SendPrepaymentPayment. Reaching that state
requires, in order:

  - Wallet.DeriveNextKey (local lnd round-trip)
  - server's RequestReservation gRPC (network + server's own lnd invoice
    creation, including hold-invoice persistence)
  - LightningClient.DecodePaymentRequest
  - Store.CreateReservation

15 seconds was achievable on a fast LAN with idle servers, but under
even modest load (server-side hold-invoice creation can routinely take
several seconds in the wild) the timer expired and the RPC returned an
error to the caller. The FSM kept running in the background and the
wallet would still pay the prepay LN invoice -- so the user got an
error, but their funds still moved. The next call to the same
reservation_id would then fail mysteriously because the server-side
state was already advanced.

Bump to 60s. The right longer-term fix is to plumb the caller's gRPC
context into the FSM SendEvent so cancellation actually aborts the
in-flight server call instead of orphaning it; that's a larger refactor
and is left as a follow-up.
This commit is contained in:
Slyghtning 2026-05-11 16:19:46 +02:00
parent b988ea8788
commit 17df6e86e6
No known key found for this signature in database
GPG key ID: F82D456EA023C9BF

View file

@ -16,7 +16,17 @@ import (
)
var (
defaultWaitForStateTime = time.Second * 15
// defaultWaitForStateTime is how long RequestReservationFromServer
// blocks waiting for the FSM to advance to SendPrepaymentPayment.
// The action that drives that transition performs a server RPC
// round-trip that itself creates an lnd hold invoice on the swap
// server side, plus an lnd DecodePaymentRequest, plus a local
// CreateReservation. Under load any one of these can take a few
// seconds, so 15s is too tight: when the RPC times out the FSM
// continues running in the background and may still pay the
// prepay invoice after the caller has been told the request
// failed. 60s gives realistic head-room.
defaultWaitForStateTime = time.Second * 60
)
// FSMSendEventReq contains the information needed to send an event to the FSM.