Documentation ¶
Index ¶
- Constants
- Variables
- func UseLogger(logger btclog.Logger)
- type AddressManager
- type BaseDB
- type Config
- type DepositManager
- type FSM
- func (f *FSM) Debugf(format string, args ...interface{})
- func (f *FSM) Errorf(format string, args ...interface{})
- func (f *FSM) Infof(format string, args ...interface{})
- func (f *FSM) InitHtlcAction(ctx context.Context, _ fsm.EventContext) fsm.EventType
- func (f *FSM) LoopInStatesV0() fsm.States
- func (f *FSM) MonitorHtlcTimeoutSweepAction(ctx context.Context, _ fsm.EventContext) fsm.EventType
- func (f *FSM) MonitorInvoiceAndHtlcTxAction(ctx context.Context, _ fsm.EventContext) fsm.EventType
- func (f *FSM) PaymentReceivedAction(ctx context.Context, _ fsm.EventContext) fsm.EventType
- func (f *FSM) SignHtlcTxAction(ctx context.Context, _ fsm.EventContext) fsm.EventType
- func (f *FSM) SweepHtlcTimeoutAction(ctx context.Context, _ fsm.EventContext) fsm.EventType
- func (f *FSM) UnlockDepositsAction(ctx context.Context, _ fsm.EventContext) fsm.EventType
- func (f *FSM) Warnf(format string, args ...interface{})
- type Manager
- func (m *Manager) DeliverLoopInRequest(ctx context.Context, req *loop.StaticAddressLoopInRequest) (*StaticAddressLoopIn, error)
- func (m *Manager) GetAllSwaps(ctx context.Context) ([]*StaticAddressLoopIn, error)
- func (m *Manager) Run(ctx context.Context, currentHeight uint32) error
- func (m *Manager) WaitInitComplete()
- type NotificationManager
- type Querier
- type QuoteGetter
- type SqlStore
- func (s *SqlStore) CreateLoopIn(ctx context.Context, loopIn *StaticAddressLoopIn) error
- func (s *SqlStore) GetLoopInByHash(ctx context.Context, swapHash lntypes.Hash) (*StaticAddressLoopIn, error)
- func (s *SqlStore) GetStaticAddressLoopInSwapsByStates(ctx context.Context, states []fsm.StateType) ([]*StaticAddressLoopIn, error)
- func (s *SqlStore) IsStored(ctx context.Context, swapHash lntypes.Hash) (bool, error)
- func (s *SqlStore) UpdateLoopIn(ctx context.Context, loopIn *StaticAddressLoopIn) error
- type StaticAddressLoopIn
- func (l *StaticAddressLoopIn) GetState() fsm.StateType
- func (l *StaticAddressLoopIn) IsInState(state fsm.StateType) bool
- func (l *StaticAddressLoopIn) Outpoints() []wire.OutPoint
- func (l *StaticAddressLoopIn) RemainingPaymentTimeSeconds() int64
- func (l *StaticAddressLoopIn) SetState(state fsm.StateType)
- func (l *StaticAddressLoopIn) TotalDepositAmount() btcutil.Amount
- type StaticAddressLoopInStore
- type ValidateLoopInContract
Constants ¶
const (
DefaultPaymentTimeoutSeconds = 60
)
const Subsystem = "SADDR"
Subsystem defines the sub system name of this package.
const ( // SwapNotFinishedMsg is the message that is sent to the server if a // swap is not considered finished yet. SwapNotFinishedMsg = "swap not finished yet" )
Variables ¶
var ( // ErrFeeTooHigh is returned if the server sets a fee rate for the htlc // tx that is too high. We prevent here against a low htlc timeout sweep // amount. ErrFeeTooHigh = errors.New("server htlc tx fee is higher than the " + "configured allowed maximum") // ErrBackupFeeTooHigh is returned if the server sets a fee rate for the // htlc backup tx that is too high. We prevent here against a low htlc // timeout sweep amount. ErrBackupFeeTooHigh = errors.New("server htlc backup tx fee is " + "higher than the configured allowed maximum") )
var ( // InitHtlcTx initiates the htlc tx creation with the server. InitHtlcTx = fsm.StateType("InitHtlcTx") // SignHtlcTx partially signs the htlc transaction with the received // server nonces. The client doesn't hold a final signature hence can't // publish the htlc. SignHtlcTx = fsm.StateType("SignHtlcTx") // MonitorInvoiceAndHtlcTx monitors the swap invoice payment and the // htlc transaction confirmation. // Since the client provided its partial signature to spend to the htlc // pkScript, the server could publish the htlc transaction prematurely. // We need to monitor the htlc transaction to sweep our timeout path in // this case. // If the server pays the swap invoice as expected we can stop to // monitor the htlc timeout path. MonitorInvoiceAndHtlcTx = fsm.StateType("MonitorInvoiceAndHtlcTx") // PaymentReceived is the state where the swap invoice was paid by the // server. The client can now sign the sweepless sweep transaction. PaymentReceived = fsm.StateType("PaymentReceived") // SweepHtlcTimeout is the state where the htlc timeout path is // published because the server did not pay the invoice on time. SweepHtlcTimeout = fsm.StateType("SweepHtlcTimeout") // MonitorHtlcTimeoutSweep monitors the htlc timeout sweep transaction // confirmation. MonitorHtlcTimeoutSweep = fsm.StateType("MonitorHtlcTimeoutSweep") // HtlcTimeoutSwept is the state where the htlc timeout sweep // transaction was sufficiently confirmed. HtlcTimeoutSwept = fsm.StateType("HtlcTimeoutSwept") // Succeeded is the state the swap is in if it was successful. Succeeded = fsm.StateType("Succeeded") // SucceededTransitioningFailed is the state the swap is in if the swap // payment was received but the client was not able to transition // the deposits to the looped-in state. SucceededTransitioningFailed = fsm.StateType("SucceededTransitioningFailed") //nolint:lll // UnlockDeposits is the state where the deposits are reset. This // happens when the state machine encountered an error and the swap // process needs to start from the beginning. UnlockDeposits = fsm.StateType("UnlockDeposits") // Failed is the state the swap is in if it failed. Failed = fsm.StateType("Failed") )
States that the loop-in fsm can transition to.
var ( OnInitHtlc = fsm.EventType("OnInitHtlc") OnHtlcInitiated = fsm.EventType("OnHtlcInitiated") OnHtlcTxSigned = fsm.EventType("OnHtlcTxSigned") OnSweepHtlcTimeout = fsm.EventType("OnSweepHtlcTimeout") OnHtlcTimeoutSweepPublished = fsm.EventType("OnHtlcTimeoutSweepPublished") OnHtlcTimeoutSwept = fsm.EventType("OnHtlcTimeoutSwept") OnPaymentReceived = fsm.EventType("OnPaymentReceived") OnPaymentDeadlineExceeded = fsm.EventType("OnPaymentDeadlineExceeded") OnSwapTimedOut = fsm.EventType("OnSwapTimedOut") OnSucceeded = fsm.EventType("OnSucceeded") OnRecover = fsm.EventType("OnRecover") )
Events.
var AllStates = append(PendingStates, FinalStates...)
var ( // ErrInvalidOutpoint is returned when an outpoint contains the outpoint // separator. ErrInvalidOutpoint = errors.New("outpoint contains outpoint separator") )
var FinalStates = []fsm.StateType{ HtlcTimeoutSwept, Succeeded, SucceededTransitioningFailed, Failed, }
var PendingStates = []fsm.StateType{ InitHtlcTx, SignHtlcTx, MonitorInvoiceAndHtlcTx, PaymentReceived, SweepHtlcTimeout, MonitorHtlcTimeoutSweep, UnlockDeposits, }
Functions ¶
Types ¶
type AddressManager ¶
type AddressManager interface { // GetStaticAddressParameters returns the static address parameters. GetStaticAddressParameters(ctx context.Context) (*address.Parameters, error) // GetStaticAddress returns the deposit address for the given client and // server public keys. GetStaticAddress(ctx context.Context) (*script.StaticAddress, error) }
AddressManager handles fetching of address parameters.
type BaseDB ¶
type BaseDB interface { Querier // ExecTx allows for executing a function in the context of a database // transaction. ExecTx(ctx context.Context, txOptions loopdb.TxOptions, txBody func(Querier) error) error }
BaseDB is the interface that contains all the queries generated by sqlc for the static_address_swaps table and transaction functionality.
type Config ¶
type Config struct { // Server is the client that is used to communicate with the static // address server. Server looprpc.StaticAddressServerClient // AddressManager gives the withdrawal manager access to static address // parameters. AddressManager AddressManager // DepositManager gives the withdrawal manager access to the deposits // enabling it to create and manage loop-ins. DepositManager DepositManager // LndClient is used to add invoices and select hop hints. LndClient lndclient.LightningClient // InvoicesClient is used to subscribe to invoice settlements and // cancel invoices. InvoicesClient lndclient.InvoicesClient // SwapClient is used to get loop in quotes. QuoteGetter QuoteGetter // NodePubKey is used to get a loo-in quote. NodePubkey route.Vertex // WalletKit is the wallet client that is used to derive new keys from // lnd's wallet. WalletKit lndclient.WalletKitClient // ChainParams is the chain configuration(mainnet, testnet...) this // manager uses. ChainParams *chaincfg.Params // Chain is the chain notifier that is used to listen for new // blocks. ChainNotifier lndclient.ChainNotifierClient // Signer is the signer client that is used to sign transactions. Signer lndclient.SignerClient // Store is the database store that is used to store static address // loop-in related records. Store StaticAddressLoopInStore // NotificationManager is the manager that handles the notification // subscriptions. NotificationManager NotificationManager // ValidateLoopInContract validates the contract parameters against our // request. ValidateLoopInContract ValidateLoopInContract // MaxStaticAddrHtlcFeePercentage is the percentage of the swap amount // that we allow the server to charge for the htlc transaction. // Although highly unlikely, this is a defense against the server // publishing the htlc without paying the swap invoice, forcing us to // sweep the timeout path. MaxStaticAddrHtlcFeePercentage float64 // MaxStaticAddrHtlcBackupFeePercentage is the percentage of the swap // amount that we allow the server to charge for the htlc backup // transactions. This is a defense against the server publishing the // htlc backup without paying the swap invoice, forcing us to sweep the // timeout path. This value is elevated compared to // MaxStaticAddrHtlcFeePercentage since it serves the server as backup // transaction in case of fee spikes. MaxStaticAddrHtlcBackupFeePercentage float64 }
Config contains the services required for the loop-in manager.
type DepositManager ¶
type DepositManager interface { // GetAllDeposits returns all known deposits from the database store. GetAllDeposits(ctx context.Context) ([]*deposit.Deposit, error) // AllStringOutpointsActiveDeposits returns all deposits that have the // given outpoints and are in the given state. If any of the outpoints // does not correspond to an active deposit, the function returns false. AllStringOutpointsActiveDeposits(outpoints []string, stateFilter fsm.StateType) ([]*deposit.Deposit, bool) // TransitionDeposits transitions the given deposits to the next state // based on the given event. It returns an error if the transition is // invalid. TransitionDeposits(ctx context.Context, deposits []*deposit.Deposit, event fsm.EventType, expectedFinalState fsm.StateType) error }
DepositManager handles the interaction of loop-ins with deposits.
type FSM ¶
type FSM struct { *fsm.StateMachine // contains filtered or unexported fields }
FSM embeds an FSM and extends it with a static address loop-in and a config.
func NewFSM ¶
func NewFSM(ctx context.Context, loopIn *StaticAddressLoopIn, cfg *Config, recoverStateMachine bool) (*FSM, error)
NewFSM creates a new loop-in state machine.
func (*FSM) InitHtlcAction ¶
InitHtlcAction is executed if all loop-in information has been validated. We assemble a loop-in request and send it to the server.
func (*FSM) LoopInStatesV0 ¶
LoopInStatesV0 returns the state and transition map for the loop-in state machine.
func (*FSM) MonitorHtlcTimeoutSweepAction ¶
MonitorHtlcTimeoutSweepAction is called after the htlc timeout sweep tx has been published. We monitor the confirmation of the htlc timeout sweep tx and finalize the deposits once swept.
func (*FSM) MonitorInvoiceAndHtlcTxAction ¶
MonitorInvoiceAndHtlcTxAction is called after the htlc tx has been signed by us. The server from here on has the ability to publish the htlc tx. If the server publishes the htlc tx without paying the invoice, we have to monitor for the timeout path and sweep the funds back to us. If, while waiting for the htlc timeout, our invoice gets paid, the swap is considered successful, and we can stop monitoring the htlc confirmation and continue to sign the sweepless sweep.
func (*FSM) PaymentReceivedAction ¶
PaymentReceivedAction is called if the invoice was settled. We finalize the deposits by transitioning them to the LoopedIn state.
func (*FSM) SignHtlcTxAction ¶
SignHtlcTxAction is called if the htlc was initialized and the server provided the necessary information to construct the htlc tx. We sign the htlc tx and send the signatures to the server.
func (*FSM) SweepHtlcTimeoutAction ¶
SweepHtlcTimeoutAction is called if the server published the htlc tx without paying the invoice. We wait for the timeout path to open up and sweep the funds back to us.
func (*FSM) UnlockDepositsAction ¶
UnlockDepositsAction is called if the loop-in failed and its deposits should be available in a future loop-in request.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager manages the address state machines.
func NewManager ¶
NewManager creates a new deposit withdrawal manager.
func (*Manager) DeliverLoopInRequest ¶
func (m *Manager) DeliverLoopInRequest(ctx context.Context, req *loop.StaticAddressLoopInRequest) (*StaticAddressLoopIn, error)
DeliverLoopInRequest forwards a loop-in request from the server to the manager run loop to initiate a new loop-in swap.
func (*Manager) GetAllSwaps ¶
func (m *Manager) GetAllSwaps(ctx context.Context) ([]*StaticAddressLoopIn, error)
GetAllSwaps returns all static address loop-in swaps from the database store.
func (*Manager) WaitInitComplete ¶
func (m *Manager) WaitInitComplete()
WaitInitComplete waits until the static address loop-in manager has completed its setup.
type NotificationManager ¶
type NotificationManager interface { // SubscribeStaticLoopInSweepRequests subscribes to the static loop in // sweep requests. These are sent by the server to the client to request // a sweep of a static loop in that has been finished. SubscribeStaticLoopInSweepRequests(ctx context.Context, ) <-chan *swapserverrpc.ServerStaticLoopInSweepNotification }
type Querier ¶
type Querier interface { // InsertSwap inserts a new base swap. InsertSwap(ctx context.Context, arg sqlc.InsertSwapParams) error // InsertHtlcKeys inserts the htlc keys for a swap. InsertHtlcKeys(ctx context.Context, arg sqlc.InsertHtlcKeysParams) error // InsertStaticAddressLoopIn inserts a new static address loop-in swap. InsertStaticAddressLoopIn(ctx context.Context, arg sqlc.InsertStaticAddressLoopInParams) error // InsertStaticAddressMetaUpdate inserts metadata about loop-in // updates. InsertStaticAddressMetaUpdate(ctx context.Context, arg sqlc.InsertStaticAddressMetaUpdateParams) error // UpdateStaticAddressLoopIn updates a loop-in swap. UpdateStaticAddressLoopIn(ctx context.Context, arg sqlc.UpdateStaticAddressLoopInParams) error // GetStaticAddressLoopInSwap retrieves a loop-in swap by its swap hash. GetStaticAddressLoopInSwap(ctx context.Context, swapHash []byte) (sqlc.GetStaticAddressLoopInSwapRow, error) // GetStaticAddressLoopInSwapsByStates retrieves all swaps with the // given states. The states string is an input for the IN primitive in // sqlite, hence the format needs to be '{State1,State2,...}'. GetStaticAddressLoopInSwapsByStates(ctx context.Context, states sql.NullString) ([]sqlc.GetStaticAddressLoopInSwapsByStatesRow, error) // GetLoopInSwapUpdates retrieves all updates for a loop-in swap. GetLoopInSwapUpdates(ctx context.Context, swapHash []byte) ([]sqlc.StaticAddressSwapUpdate, error) // IsStored returns true if a swap with the given hash is stored in the // database, false otherwise. IsStored(ctx context.Context, swapHash []byte) (bool, error) }
Querier is the interface that contains all the queries generated by sqlc for the static_address_swaps table.
type QuoteGetter ¶
type SqlStore ¶
type SqlStore struct {
// contains filtered or unexported fields
}
SqlStore is the backing store for static address loop-ins.
func NewSqlStore ¶
NewSqlStore constructs a new SQLStore from a BaseDB. The BaseDB is agnostic to the underlying driver which can be postgres or sqlite.
func (*SqlStore) CreateLoopIn ¶
func (s *SqlStore) CreateLoopIn(ctx context.Context, loopIn *StaticAddressLoopIn) error
CreateLoopIn inserts a new loop-in swap into the database. Basic loop-in parameters are stored in the swaps table, htlc key information is stored in the htlc_keys table, and loop-in specific information is stored in the static_address_swaps table.
func (*SqlStore) GetLoopInByHash ¶
func (s *SqlStore) GetLoopInByHash(ctx context.Context, swapHash lntypes.Hash) (*StaticAddressLoopIn, error)
GetLoopInByHash returns the loop-in swap with the given hash.
func (*SqlStore) GetStaticAddressLoopInSwapsByStates ¶
func (s *SqlStore) GetStaticAddressLoopInSwapsByStates(ctx context.Context, states []fsm.StateType) ([]*StaticAddressLoopIn, error)
GetStaticAddressLoopInSwapsByStates returns all static address loop-ins from the db that are in the given states.
func (*SqlStore) IsStored ¶
IsStored returns true if a swap with the given hash is stored in the database, false otherwise.
func (*SqlStore) UpdateLoopIn ¶
func (s *SqlStore) UpdateLoopIn(ctx context.Context, loopIn *StaticAddressLoopIn) error
UpdateLoopIn updates the loop-in in the database.
type StaticAddressLoopIn ¶
type StaticAddressLoopIn struct { // SwapHash is the hashed preimage of the swap invoice. It represents // the primary identifier of the swap. SwapHash lntypes.Hash // SwapPreimage is the preimage that is used for the swap. SwapPreimage lntypes.Preimage // HtlcCltvExpiry is the expiry of the swap. HtlcCltvExpiry int32 // MaxSwapFee is the swap fee in sats that the user accepted when // initiating the swap. It is the upper limit for the QuotedSwapFee. MaxSwapFee btcutil.Amount // InitiationHeight is the height at which the swap was initiated. InitiationHeight uint32 // InitiationTime is the time at which the swap was initiated. InitiationTime time.Time // ProtocolVersion is the protocol version of the static address. ProtocolVersion version.AddressProtocolVersion // Label contains an optional label for the swap. Label string // ClientPubkey is the pubkey of the client that is used for the swap. ClientPubkey *btcec.PublicKey // ServerPubkey is the pubkey of the server that is used for the swap. ServerPubkey *btcec.PublicKey // HtlcKeyLocator is the locator of the server's htlc key. HtlcKeyLocator keychain.KeyLocator // SwapInvoice is the invoice that needs to be paid by the server to // complete the loop-in swap. SwapInvoice string // LastHop is an optional parameter that specifies the last hop to be // used for a loop in swap. LastHop []byte // The swap payment timeout allows the user to specify an upper limit // for the amount of time the server is allowed to take to fulfill the // off-chain swap payment. If the timeout is reached the swap will be // aborted on the server side and the client can retry the swap with // different parameters. PaymentTimeoutSeconds uint32 // QuotedSwapFee is the swap fee in sats that the server returned in the // swap quote. QuotedSwapFee btcutil.Amount // The outpoints in the format txid:vout that are part of the loop-in // swap. DepositOutpoints []string // Initiator is an optional identification string that will be appended // to the user agent string sent to the server to give information about // the usage of loop. This initiator part is meant for user interfaces // to add their name to give the full picture of the binary used // (loopd, lit) and the method used for triggering the swap // (loop cli, autolooper, lit ui, other 3rd party ui). Initiator string // Private indicates whether the destination node should be considered // private. In which case, loop will generate hop hints to assist with // probing and payment. Private bool // Optional route hints to reach the destination through private // channels. RouteHints [][]zpay32.HopHint // Deposits are the deposits that are part of the loop-in swap. They // implicitly carry the swap amount. Deposits []*deposit.Deposit // AddressParams are the parameters of the address that is used for the // swap. AddressParams *address.Parameters // Address is the address script that is used for the swap. Address *script.StaticAddress // HtlcTxFeeRate is the fee rate that is used for the htlc transaction. HtlcTxFeeRate chainfee.SatPerKWeight // HtlcTxHighFeeRate is the fee rate that is used for the htlc // transaction. HtlcTxHighFeeRate chainfee.SatPerKWeight // HtlcTxExtremelyHighFeeRate is the fee rate that is used for the htlc // transaction. HtlcTxExtremelyHighFeeRate chainfee.SatPerKWeight // HtlcTimeoutSweepTxHash is the hash of the htlc timeout sweep tx. HtlcTimeoutSweepTxHash *chainhash.Hash // HtlcTimeoutSweepAddress HtlcTimeoutSweepAddress btcutil.Address // contains filtered or unexported fields }
StaticAddressLoopIn represents the in-memory loop-in information.
func (*StaticAddressLoopIn) GetState ¶
func (l *StaticAddressLoopIn) GetState() fsm.StateType
GetState returns the current state of the loop-in swap.
func (*StaticAddressLoopIn) IsInState ¶
func (l *StaticAddressLoopIn) IsInState(state fsm.StateType) bool
IsInState returns true if the deposit is in the given state.
func (*StaticAddressLoopIn) Outpoints ¶
func (l *StaticAddressLoopIn) Outpoints() []wire.OutPoint
Outpoints returns the wire outpoints of the deposits.
func (*StaticAddressLoopIn) RemainingPaymentTimeSeconds ¶
func (l *StaticAddressLoopIn) RemainingPaymentTimeSeconds() int64
RemainingPaymentTimeSeconds returns the remaining time in seconds until the payment timeout is reached. The remaining time is calculated from the initiation time of the swap. If more than the swaps configured payment timeout has passed, the remaining time will be negative.
func (*StaticAddressLoopIn) SetState ¶
func (l *StaticAddressLoopIn) SetState(state fsm.StateType)
SetState sets the current state of the loop-in swap.
func (*StaticAddressLoopIn) TotalDepositAmount ¶
func (l *StaticAddressLoopIn) TotalDepositAmount() btcutil.Amount
TotalDepositAmount returns the total amount of the deposits.
type StaticAddressLoopInStore ¶
type StaticAddressLoopInStore interface { // CreateLoopIn creates a loop-in record in the database. CreateLoopIn(ctx context.Context, loopIn *StaticAddressLoopIn) error // UpdateLoopIn updates a loop-in record in the database. UpdateLoopIn(ctx context.Context, loopIn *StaticAddressLoopIn) error // GetStaticAddressLoopInSwapsByStates returns all loop-ins with given // states. GetStaticAddressLoopInSwapsByStates(ctx context.Context, states []fsm.StateType) ([]*StaticAddressLoopIn, error) // IsStored checks if the loop-in is already stored in the database. IsStored(ctx context.Context, swapHash lntypes.Hash) (bool, error) // GetLoopInByHash returns the loop-in swap with the given hash. GetLoopInByHash(ctx context.Context, swapHash lntypes.Hash) ( *StaticAddressLoopIn, error) }
StaticAddressLoopInStore provides access to the static address loop-in DB.
type ValidateLoopInContract ¶
ValidateLoopInContract validates the contract parameters against our request.