If the PSBT finalize step succeeds but the stream fails before
ChanPending, deposits would remain stuck in OpeningChannel until the
next daemon restart. Run the recovery logic immediately so deposits are
resolved without requiring a restart.
Also, add tests for the following edge cases requested in review:
- Reorg: channel tx reorged, UTXOs reappear as unspent, deposits
return to Deposited state.
- Daemon restart during channel opening: deposits in OpeningChannel
recovered based on UTXO status (spent → ChannelPublished, unspent →
Deposited).
- Mempool eviction: tx evicted, UTXOs unspent, deposits return to
Deposited.
- Mempool rejection: tx never accepted, same recovery as eviction.
- Stream errors: lnd stream fails before PSBT finalize, error returned
without errPsbtFinalized so deposits can be safely rolled back.
- PSBT finalize then stream abort: finalize succeeds but stream dies
before ChanPending, error wrapped with errPsbtFinalized so caller
triggers recovery instead of blind rollback.
- Duplicate outpoints: already covered by TestOpenChannelDuplicateOutpoints.
Duplicate outpoints in the request lead to fee miscalculation and an
invalid PSBT with the same input listed twice. Validate early and return
a clear error message.
Both OpeningChannel and ChannelPublished lacked OnExpiry transitions.
handleBlockNotification fires OnExpiry on every new block once the
deposit is expired, regardless of the current state. Since both states
use NoOpAction or FinalizeDepositAction which release the FSM mutex
briefly, an OnExpiry SendEvent can sneak in. Add self-transitions so
the event is safely absorbed.
Return an error instead of just logging when chainhash.NewHash fails in
the ChanPending handler. The hash variable would be nil and crash on the
subsequent String() call.
Protect the shimPending variable with a sync.Mutex since it is accessed
from multiple goroutines: the main loop goroutine and the server error
handling goroutine. Without synchronization this is a data race.
Block-based deposit fetching from the internal lnd wallet was
susceptible to wallet syncing issues. Replace it with interval-based
polling. Reconciliation errors are now logged instead of being fatal,
improving resilience during transient failures.
Remove unreachable error check after filterNewDeposits which does not
return an error. The err variable was already handled from the
ListUnspent call above and could never be non-nil at this point.
Add macaroon permissions for the new StaticOpenChannel RPC method
and change StaticAddressLoopIn action from read to execute to match
other swap operations.
In this commit we import the lnd's lightning.proto into client.proto to
then be able to use lnrpc.OutPoint and lnrpc.OpenChannelRequest instead
of the looprpc.OutPoint type.
This is safe because the lnrpc and looprpc versions of OutPoint are the
same type.
In successive commits we want to access lnrpc specifc methods
and objects, so here we import github.com/lightningnetwork/lnd v0.20.1-beta
into looprpc and update relevant versions.
- Change return signature of startNewLoopIn from (*swapConfig, error, *loopInSwap) to (*swapConfig, *loopInSwap, error)
- Fixes ST1008: error should be returned as the last argument