Documentation ¶
Index ¶
- Constants
- Variables
- func DefaultNextAttemptDeltaFunc(attempts int) int32
- func DetermineFeePerKw(feeEstimator chainfee.Estimator, feePref FeePreference) (chainfee.SatPerKWeight, er.R)
- type CoinSelectionLocker
- type FeePreference
- type MockNotifier
- func (m *MockNotifier) ConfirmTx(txid *chainhash.Hash, height uint32) er.R
- func (m *MockNotifier) NotifyEpoch(height int32)
- func (m *MockNotifier) RegisterBlockEpochNtfn(bestBlock *chainntnfs.BlockEpoch) (*chainntnfs.BlockEpochEvent, er.R)
- func (m *MockNotifier) RegisterConfirmationsNtfn(txid *chainhash.Hash, _ []byte, numConfs, heightHint uint32) (*chainntnfs.ConfirmationEvent, er.R)
- func (m *MockNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, _ []byte, heightHint uint32) (*chainntnfs.SpendEvent, er.R)
- func (m *MockNotifier) SpendOutpoint(outpoint wire.OutPoint, spendingTx wire.MsgTx)
- func (m *MockNotifier) Start() er.R
- func (m *MockNotifier) Started() bool
- func (m *MockNotifier) Stop() er.R
- type MockSweeperStore
- type OutpointLocker
- type Params
- type ParamsUpdate
- type PendingInput
- type Result
- type SweeperStore
- type UtxoSource
- type UtxoSweeper
- func (s *UtxoSweeper) CreateSweepTx(inputs []input.Input, feePref FeePreference, currentBlockHeight uint32) (*wire.MsgTx, er.R)
- func (s *UtxoSweeper) ListSweeps() ([]chainhash.Hash, er.R)
- func (s *UtxoSweeper) PendingInputs() (map[wire.OutPoint]*PendingInput, er.R)
- func (s *UtxoSweeper) RelayFeePerKW() chainfee.SatPerKWeight
- func (s *UtxoSweeper) Start() er.R
- func (s *UtxoSweeper) Stop() er.R
- func (s *UtxoSweeper) SweepInput(input input.Input, params Params) (chan Result, er.R)
- func (s *UtxoSweeper) UpdateParams(input wire.OutPoint, params ParamsUpdate) (chan Result, er.R)
- type UtxoSweeperConfig
- type Wallet
- type WalletSweepPackage
Constants ¶
const ( // DefaultMaxFeeRate is the default maximum fee rate allowed within the // UtxoSweeper. The current value is equivalent to a fee rate of 10,000 // sat/vbyte. DefaultMaxFeeRate = chainfee.FeePerKwFloor * 1e4 // DefaultFeeRateBucketSize is the default size of fee rate buckets // we'll use when clustering inputs into buckets with similar fee rates // within the UtxoSweeper. // // Given a minimum relay fee rate of 1 sat/vbyte, a multiplier of 10 // would result in the following fee rate buckets up to the maximum fee // rate: // // #1: min = 1 sat/vbyte, max = 10 sat/vbyte // #2: min = 11 sat/vbyte, max = 20 sat/vbyte... DefaultFeeRateBucketSize = 10 )
Variables ¶
var ( Err = er.NewErrorType("lnd.sweep") // ErrRemoteSpend is returned in case an output that we try to sweep is // confirmed in a tx of the remote party. ErrRemoteSpend = Err.CodeWithDetail("ErrRemoteSpend", "remote party swept utxo") // ErrTooManyAttempts is returned in case sweeping an output has failed // for the configured max number of attempts. ErrTooManyAttempts = Err.CodeWithDetail("ErrTooManyAttempts", "sweep failed after max attempts") // ErrNoFeePreference is returned when we attempt to satisfy a sweep // request from a client whom did not specify a fee preference. ErrNoFeePreference = Err.CodeWithDetail("ErrNoFeePreference", "no fee preference specified") // ErrExclusiveGroupSpend is returned in case a different input of the // same exclusive group was spent. ErrExclusiveGroupSpend = Err.CodeWithDetail("ErrExclusiveGroupSpend", "other member of exclusive group was spent") // ErrSweeperShuttingDown is an error returned when a client attempts to // make a request to the UtxoSweeper, but it is unable to handle it as // it is/has already been stopped. ErrSweeperShuttingDown = Err.CodeWithDetail("ErrSweeperShuttingDown", "utxo sweeper shutting down") // DefaultMaxSweepAttempts specifies the default maximum number of times // an input is included in a publish attempt before giving up and // returning an error to the caller. DefaultMaxSweepAttempts = 10 )
var ( // DefaultBatchWindowDuration specifies duration of the sweep batch // window. The sweep is held back during the batch window to allow more // inputs to be added and thereby lower the fee per input. DefaultBatchWindowDuration = 30 * time.Second )
var ( // DefaultMaxInputsPerTx specifies the default maximum number of inputs // allowed in a single sweep tx. If more need to be swept, multiple txes // are created and published. DefaultMaxInputsPerTx = 100 )
Functions ¶
func DefaultNextAttemptDeltaFunc ¶
DefaultNextAttemptDeltaFunc is the default calculation for next sweep attempt scheduling. It implements exponential back-off with some randomness. This is to prevent a stuck tx (for example because fee is too low and can't be bumped in btcd) from blocking all other retried inputs in the same tx.
func DetermineFeePerKw ¶
func DetermineFeePerKw(feeEstimator chainfee.Estimator, feePref FeePreference) (chainfee.SatPerKWeight, er.R)
DetermineFeePerKw will determine the fee in sat/kw that should be paid given an estimator, a confirmation target, and a manual value for sat/byte. A value is chosen based on the two free parameters as one, or both of them can be zero.
Types ¶
type CoinSelectionLocker ¶
type CoinSelectionLocker interface { // WithCoinSelectLock will execute the passed function closure in a // synchronized manner preventing any coin selection operations from // proceeding while the closure is executing. This can be seen as the // ability to execute a function closure under an exclusive coin // selection lock. WithCoinSelectLock(func() er.R) er.R }
CoinSelectionLocker is an interface that allows the caller to perform an operation, which is synchronized with all coin selection attempts. This can be used when an operation requires that all coin selection operations cease forward progress. Think of this as an exclusive lock on coin selection operations.
type FeePreference ¶
type FeePreference struct { // ConfTarget if non-zero, signals a fee preference expressed in the // number of desired blocks between first broadcast, and confirmation. ConfTarget uint32 // FeeRate if non-zero, signals a fee pre fence expressed in the fee // rate expressed in sat/kw for a particular transaction. FeeRate chainfee.SatPerKWeight }
FeePreference allows callers to express their time value for inclusion of a transaction into a block via either a confirmation target, or a fee rate.
func (FeePreference) String ¶
func (p FeePreference) String() string
String returns a human-readable string of the fee preference.
type MockNotifier ¶
type MockNotifier struct {
// contains filtered or unexported fields
}
MockNotifier simulates the chain notifier for test purposes. This type is exported because it is used in nursery tests.
func NewMockNotifier ¶
func NewMockNotifier(t *testing.T) *MockNotifier
NewMockNotifier instantiates a new mock notifier.
func (*MockNotifier) NotifyEpoch ¶
func (m *MockNotifier) NotifyEpoch(height int32)
NotifyEpoch simulates a new epoch arriving.
func (*MockNotifier) RegisterBlockEpochNtfn ¶
func (m *MockNotifier) RegisterBlockEpochNtfn( bestBlock *chainntnfs.BlockEpoch) (*chainntnfs.BlockEpochEvent, er.R)
RegisterBlockEpochNtfn registers a block notification.
func (*MockNotifier) RegisterConfirmationsNtfn ¶
func (m *MockNotifier) RegisterConfirmationsNtfn(txid *chainhash.Hash, _ []byte, numConfs, heightHint uint32) (*chainntnfs.ConfirmationEvent, er.R)
RegisterConfirmationsNtfn registers for tx confirm notifications.
func (*MockNotifier) RegisterSpendNtfn ¶
func (m *MockNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, _ []byte, heightHint uint32) (*chainntnfs.SpendEvent, er.R)
RegisterSpendNtfn registers for spend notifications.
func (*MockNotifier) SpendOutpoint ¶
func (m *MockNotifier) SpendOutpoint(outpoint wire.OutPoint, spendingTx wire.MsgTx)
SpendOutpoint simulates a utxo being spent.
type MockSweeperStore ¶
type MockSweeperStore struct {
// contains filtered or unexported fields
}
MockSweeperStore is a mock implementation of sweeper store. This type is exported, because it is currently used in nursery tests too.
func NewMockSweeperStore ¶
func NewMockSweeperStore() *MockSweeperStore
NewMockSweeperStore returns a new instance.
func (*MockSweeperStore) GetLastPublishedTx ¶
func (s *MockSweeperStore) GetLastPublishedTx() (*wire.MsgTx, er.R)
GetLastPublishedTx returns the last tx that we called NotifyPublishTx for.
func (*MockSweeperStore) IsOurTx ¶
IsOurTx determines whether a tx is published by us, based on its hash.
func (*MockSweeperStore) ListSweeps ¶
func (s *MockSweeperStore) ListSweeps() ([]chainhash.Hash, er.R)
ListSweeps lists all the sweeps we have successfully published.
func (*MockSweeperStore) NotifyPublishTx ¶
func (s *MockSweeperStore) NotifyPublishTx(tx *wire.MsgTx) er.R
NotifyPublishTx signals that we are about to publish a tx.
type OutpointLocker ¶
type OutpointLocker interface { // LockOutpoint locks a target outpoint, rendering it unusable for coin // selection. LockOutpoint(o wire.OutPoint) // UnlockOutpoint unlocks a target outpoint, allowing it to be used for // coin selection once again. UnlockOutpoint(o wire.OutPoint) }
OutpointLocker allows a caller to lock/unlock an outpoint. When locked, the outpoints shouldn't be used for any sort of channel funding of coin selection. Locked outpoints are not expected to be persisted between restarts.
type Params ¶
type Params struct { // Fee is the fee preference of the client who requested the input to be // swept. If a confirmation target is specified, then we'll map it into // a fee rate whenever we attempt to cluster inputs for a sweep. Fee FeePreference // Force indicates whether the input should be swept regardless of // whether it is economical to do so. Force bool // ExclusiveGroup is an identifier that, if set, prevents other inputs // with the same identifier from being batched together. ExclusiveGroup *uint64 }
Params contains the parameters that control the sweeping process.
type ParamsUpdate ¶
type ParamsUpdate struct { // Fee is the fee preference of the client who requested the input to be // swept. If a confirmation target is specified, then we'll map it into // a fee rate whenever we attempt to cluster inputs for a sweep. Fee FeePreference // Force indicates whether the input should be swept regardless of // whether it is economical to do so. Force bool }
ParamsUpdate contains a new set of parameters to update a pending sweep with.
type PendingInput ¶
type PendingInput struct { // OutPoint is the identify outpoint of the input being swept. OutPoint wire.OutPoint // WitnessType is the witness type of the input being swept. WitnessType input.WitnessType // Amount is the amount of the input being swept. Amount btcutil.Amount // LastFeeRate is the most recent fee rate used for the input being // swept within a transaction broadcast to the network. LastFeeRate chainfee.SatPerKWeight // BroadcastAttempts is the number of attempts we've made to sweept the // input. BroadcastAttempts int // NextBroadcastHeight is the next height of the chain at which we'll // attempt to broadcast a transaction sweeping the input. NextBroadcastHeight uint32 // Params contains the sweep parameters for this pending request. Params Params }
PendingInput contains information about an input that is currently being swept by the UtxoSweeper.
type Result ¶
type Result struct { // Err is the final result of the sweep. It is nil when the input is // swept successfully by us. ErrRemoteSpend is returned when another // party took the input. Err er.R // Tx is the transaction that spent the input. Tx *wire.MsgTx }
Result is the struct that is pushed through the result channel. Callers can use this to be informed of the final sweep result. In case of a remote spend, Err will be ErrRemoteSpend.
type SweeperStore ¶
type SweeperStore interface { // IsOurTx determines whether a tx is published by us, based on its // hash. IsOurTx(hash chainhash.Hash) (bool, er.R) // NotifyPublishTx signals that we are about to publish a tx. NotifyPublishTx(*wire.MsgTx) er.R // GetLastPublishedTx returns the last tx that we called NotifyPublishTx // for. GetLastPublishedTx() (*wire.MsgTx, er.R) // ListSweeps lists all the sweeps we have successfully published. ListSweeps() ([]chainhash.Hash, er.R) }
SweeperStore stores published txes.
func NewSweeperStore ¶
NewSweeperStore returns a new store instance.
type UtxoSource ¶
type UtxoSource interface { // ListUnspentWitness returns all UTXOs from the source that have // between minConfs and maxConfs number of confirmations. ListUnspentWitness(minConfs, maxConfs int32) ([]*lnwallet.Utxo, er.R) }
UtxoSource is an interface that allows a caller to access a source of UTXOs to use when crafting sweep transactions.
type UtxoSweeper ¶
type UtxoSweeper struct {
// contains filtered or unexported fields
}
UtxoSweeper is responsible for sweeping outputs back into the wallet
func (*UtxoSweeper) CreateSweepTx ¶
func (s *UtxoSweeper) CreateSweepTx(inputs []input.Input, feePref FeePreference, currentBlockHeight uint32) (*wire.MsgTx, er.R)
CreateSweepTx accepts a list of inputs and signs and generates a txn that spends from them. This method also makes an accurate fee estimate before generating the required witnesses.
The created transaction has a single output sending all the funds back to the source wallet, after accounting for the fee estimate.
The value of currentBlockHeight argument will be set as the tx locktime. This function assumes that all CLTV inputs will be unlocked after currentBlockHeight. Reasons not to use the maximum of all actual CLTV expiry values of the inputs:
- Make handling re-orgs easier. - Thwart future possible fee sniping attempts. - Make us blend in with the bitcoind wallet.
func (*UtxoSweeper) ListSweeps ¶
func (s *UtxoSweeper) ListSweeps() ([]chainhash.Hash, er.R)
ListSweeps returns a list of the the sweeps recorded by the sweep store.
func (*UtxoSweeper) PendingInputs ¶
func (s *UtxoSweeper) PendingInputs() (map[wire.OutPoint]*PendingInput, er.R)
PendingInputs returns the set of inputs that the UtxoSweeper is currently attempting to sweep.
func (*UtxoSweeper) RelayFeePerKW ¶
func (s *UtxoSweeper) RelayFeePerKW() chainfee.SatPerKWeight
RelayFeePerKW returns the minimum fee rate required for transactions to be relayed.
func (*UtxoSweeper) Start ¶
func (s *UtxoSweeper) Start() er.R
Start starts the process of constructing and publish sweep txes.
func (*UtxoSweeper) Stop ¶
func (s *UtxoSweeper) Stop() er.R
Stop stops sweeper from listening to block epochs and constructing sweep txes.
func (*UtxoSweeper) SweepInput ¶
SweepInput sweeps inputs back into the wallet. The inputs will be batched and swept after the batch time window ends. A custom fee preference can be provided to determine what fee rate should be used for the input. Note that the input may not always be swept with this exact value, as its possible for it to be batched under the same transaction with other similar fee rate inputs.
NOTE: Extreme care needs to be taken that input isn't changed externally. Because it is an interface and we don't know what is exactly behind it, we cannot make a local copy in sweeper.
func (*UtxoSweeper) UpdateParams ¶
func (s *UtxoSweeper) UpdateParams(input wire.OutPoint, params ParamsUpdate) (chan Result, er.R)
UpdateParams allows updating the sweep parameters of a pending input in the UtxoSweeper. This function can be used to provide an updated fee preference and force flag that will be used for a new sweep transaction of the input that will act as a replacement transaction (RBF) of the original sweeping transaction, if any. The exclusive group is left unchanged.
NOTE: This currently doesn't do any fee rate validation to ensure that a bump is actually successful. The responsibility of doing so should be handled by the caller.
type UtxoSweeperConfig ¶
type UtxoSweeperConfig struct { // GenSweepScript generates a P2WKH script belonging to the wallet where // funds can be swept. GenSweepScript func() ([]byte, er.R) // FeeEstimator is used when crafting sweep transactions to estimate // the necessary fee relative to the expected size of the sweep // transaction. FeeEstimator chainfee.Estimator // Wallet contains the wallet functions that sweeper requires. Wallet Wallet // NewBatchTimer creates a channel that will be sent on when a certain // time window has passed. During this time window, new inputs can still // be added to the sweep tx that is about to be generated. NewBatchTimer func() <-chan time.Time // Notifier is an instance of a chain notifier we'll use to watch for // certain on-chain events. Notifier chainntnfs.ChainNotifier // Store stores the published sweeper txes. Store SweeperStore // Signer is used by the sweeper to generate valid witnesses at the // time the incubated outputs need to be spent. Signer input.Signer // MaxInputsPerTx specifies the default maximum number of inputs allowed // in a single sweep tx. If more need to be swept, multiple txes are // created and published. MaxInputsPerTx int // MaxSweepAttempts specifies the maximum number of times an input is // included in a publish attempt before giving up and returning an error // to the caller. MaxSweepAttempts int // NextAttemptDeltaFunc returns given the number of already attempted // sweeps, how many blocks to wait before retrying to sweep. NextAttemptDeltaFunc func(int) int32 // MaxFeeRate is the the maximum fee rate allowed within the // UtxoSweeper. MaxFeeRate chainfee.SatPerKWeight // FeeRateBucketSize is the default size of fee rate buckets we'll use // when clustering inputs into buckets with similar fee rates within the // UtxoSweeper. // // Given a minimum relay fee rate of 1 sat/vbyte, a fee rate bucket size // of 10 would result in the following fee rate buckets up to the // maximum fee rate: // // #1: min = 1 sat/vbyte, max (exclusive) = 11 sat/vbyte // #2: min = 11 sat/vbyte, max (exclusive) = 21 sat/vbyte... FeeRateBucketSize int }
UtxoSweeperConfig contains dependencies of UtxoSweeper.
type Wallet ¶
type Wallet interface { // PublishTransaction performs cursory validation (dust checks, etc) and // broadcasts the passed transaction to the Bitcoin network. PublishTransaction(tx *wire.MsgTx, label string) er.R // ListUnspentWitness returns all unspent outputs which are version 0 // witness programs. The 'minconfirms' and 'maxconfirms' parameters // indicate the minimum and maximum number of confirmations an output // needs in order to be returned by this method. ListUnspentWitness(minconfirms, maxconfirms int32) ([]*lnwallet.Utxo, er.R) // WithCoinSelectLock will execute the passed function closure in a // synchronized manner preventing any coin selection operations from // proceeding while the closure is executing. This can be seen as the // ability to execute a function closure under an exclusive coin // selection lock. WithCoinSelectLock(f func() er.R) er.R }
Wallet contains all wallet related functionality required by sweeper.
type WalletSweepPackage ¶
type WalletSweepPackage struct { // SweepTx is a fully signed, and valid transaction that is broadcast, // will sweep ALL confirmed coins in the wallet with a single // transaction. SweepTx *wire.MsgTx // CancelSweepAttempt allows the caller to cancel the sweep attempt. // // NOTE: If the sweeping transaction isn't or cannot be broadcast, then // this closure MUST be called, otherwise all selected utxos will be // unable to be used. CancelSweepAttempt func() }
WalletSweepPackage is a package that gives the caller the ability to sweep ALL funds from a wallet in a single transaction. We also package a function closure that allows one to abort the operation.
func CraftSweepAllTx ¶
func CraftSweepAllTx(feeRate chainfee.SatPerKWeight, dustLimit btcutil.Amount, blockHeight uint32, deliveryAddr btcutil.Address, coinSelectLocker CoinSelectionLocker, utxoSource UtxoSource, outpointLocker OutpointLocker, feeEstimator chainfee.Estimator, signer input.Signer) (*WalletSweepPackage, er.R)
CraftSweepAllTx attempts to craft a WalletSweepPackage which will allow the caller to sweep ALL outputs within the wallet to a single UTXO, as specified by the delivery address. The sweep transaction will be crafted with the target fee rate, and will use the utxoSource and outpointLocker as sources for wallet funds.