package loopdb import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" ) // SwapState indicates the current state of a swap. This enumeration is the // union of loop in and loop out states. A single type is used for both swap // types to be able to reduce code duplication that would otherwise be required. type SwapState uint8 const ( // StateInitiated is the initial state of a swap. At that point, the // initiation call to the server has been made and the payment process // has been started for the swap and prepayment invoices. StateInitiated SwapState = 0 // StatePreimageRevealed is reached when the sweep tx publication is // first attempted. From that point on, we should consider the preimage // to no longer be secret and we need to do all we can to get the sweep // confirmed. This state will mostly coalesce with StateHtlcConfirmed, // except in the case where we wait for fees to come down before we // sweep. StatePreimageRevealed SwapState = 1 // StateSuccess is the final swap state that is reached when the sweep // tx has the required confirmation depth (SweepConfDepth) and the // server pulled the off-chain htlc. StateSuccess SwapState = 2 // StateFailOffchainPayments indicates that it wasn't possible to find // routes for one or both of the off-chain payments to the server that // satisfied the payment restrictions (fee and timelock limits). StateFailOffchainPayments SwapState = 3 // StateFailTimeout indicates that the on-chain htlc wasn't confirmed // before its expiry or confirmed too late (MinPreimageRevealDelta // violated). StateFailTimeout SwapState = 4 // StateFailSweepTimeout indicates that the on-chain htlc wasn't swept // before the server revoked the htlc. The server didn't pull the // off-chain htlc (even though it could have) and we timed out the // off-chain htlc ourselves. No funds lost. StateFailSweepTimeout SwapState = 5 // StateFailInsufficientValue indicates that the published on-chain htlc // had a value lower than the requested amount. StateFailInsufficientValue SwapState = 6 // StateFailTemporary indicates that the swap cannot progress because // of an internal error. This is not a final state. Manual intervention // (like a restart) is required to solve this problem. StateFailTemporary SwapState = 7 // StateHtlcPublished means that the client published the on-chain htlc. StateHtlcPublished SwapState = 8 // StateInvoiceSettled means that the swap invoice has been paid by the // server. StateInvoiceSettled SwapState = 9 // StateFailIncorrectHtlcAmt indicates that the amount of an externally // published loop in htlc didn't match the swap amount. StateFailIncorrectHtlcAmt SwapState = 10 // StateFailAbandoned indicates that a swap has been abandoned. Its // execution has been canceled. It won't further be processed. StateFailAbandoned SwapState = 11 // StateFailInsufficientConfirmedBalance indicates that the swap wasn't // published due to insufficient confirmed balance. StateFailInsufficientConfirmedBalance SwapState = 12 // StateFailIncorrectHtlcAmtSwept indicates that the amount of an // externally published loop in htlc that didn't match the swap amount // has been swept back to the user after the htlc timeout period. StateFailIncorrectHtlcAmtSwept SwapState = 13 ) // SwapStateType defines the types of swap states that exist. Every swap state // defined as type SwapState above, falls into one of these SwapStateType // categories. type SwapStateType uint8 const ( // StateTypePending indicates that the swap is still pending. StateTypePending SwapStateType = 0 // StateTypeSuccess indicates that the swap has completed successfully. StateTypeSuccess = 1 // StateTypeFail indicates that the swap has failed. StateTypeFail = 2 ) // Type returns the type of the SwapState it is called on. func (s SwapState) Type() SwapStateType { if s.IsPending() { return StateTypePending } if s == StateSuccess { return StateTypeSuccess } return StateTypeFail } // IsPending returns true if the swap is in a pending state. func (s SwapState) IsPending() bool { return s == StateInitiated || s == StateHtlcPublished || s == StatePreimageRevealed || s == StateFailTemporary || s == StateInvoiceSettled || s == StateFailIncorrectHtlcAmt } // IsFinal returns true if the swap is in a final state. func (s SwapState) IsFinal() bool { return !s.IsPending() } // String returns a string representation of the swap's state. func (s SwapState) String() string { switch s { case StateInitiated: return "Initiated" case StatePreimageRevealed: return "PreimageRevealed" case StateHtlcPublished: return "HtlcPublished" case StateSuccess: return "Success" case StateFailOffchainPayments: return "FailOffchainPayments" case StateFailTimeout: return "FailTimeout" case StateFailSweepTimeout: return "FailSweepTimeout" case StateFailInsufficientValue: return "FailInsufficientValue" case StateFailTemporary: return "FailTemporary" case StateInvoiceSettled: return "InvoiceSettled" case StateFailIncorrectHtlcAmt: return "IncorrectHtlcAmt" case StateFailAbandoned: return "FailAbandoned" case StateFailInsufficientConfirmedBalance: return "InsufficientConfirmedBalance" case StateFailIncorrectHtlcAmtSwept: return "StateFailIncorrectHtlcAmtSwept" default: return "Unknown" } } // SwapCost is a breakdown of the final swap costs. type SwapCost struct { // Swap is the amount paid to the server. Server btcutil.Amount // Onchain is the amount paid to miners for the onchain tx. Onchain btcutil.Amount // Offchain is the amount paid in routing fees. Offchain btcutil.Amount } // Total returns the total costs represented by swap costs. func (s SwapCost) Total() btcutil.Amount { return s.Server + s.Onchain + s.Offchain } // SwapStateData is all persistent data to describe the current swap state. type SwapStateData struct { // SwapState is the state the swap is in. State SwapState // Cost are the accrued (final) costs so far. Cost SwapCost // HtlcTxHash is the tx id of the confirmed htlc. HtlcTxHash *chainhash.Hash }