sweep

package
v0.0.0-...-9dd16ae Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 3, 2021 License: MIT Imports: 27 Imported by: 0

Documentation

Index

Constants

View Source
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

View Source
var (
	// ErrRemoteSpend is returned in case an output that we try to sweep is
	// confirmed in a tx of the remote party.
	ErrRemoteSpend = errors.New("remote party swept utxo")

	// ErrTooManyAttempts is returned in case sweeping an output has failed
	// for the configured max number of attempts.
	ErrTooManyAttempts = errors.New("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 = errors.New("no fee preference specified")

	// ErrExclusiveGroupSpend is returned in case a different input of the
	// same exclusive group was spent.
	ErrExclusiveGroupSpend = errors.New("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 = errors.New("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
)
View Source
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
)
View Source
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

func DefaultNextAttemptDeltaFunc(attempts int) int32

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 eacd) from blocking all other retried inputs in the same tx.

func DetermineFeePerKw

func DetermineFeePerKw(feeEstimator chainfee.Estimator,
	feePref FeePreference) (chainfee.SatPerKWeight, error)

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.

func DisableLog

func DisableLog()

DisableLog disables all library log output. Logging output is disabled by default until UseLogger is called.

func UseLogger

func UseLogger(logger btclog.Logger)

UseLogger uses a specified Logger to output package logging info. This should be used in preference to SetLogWriter if the caller is also using btclog.

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() error) error
}

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) ConfirmTx

func (m *MockNotifier) ConfirmTx(txid *chainhash.Hash, height uint32) error

ConfirmTx simulates a tx confirming.

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, error)

RegisterBlockEpochNtfn registers a block notification.

func (*MockNotifier) RegisterConfirmationsNtfn

func (m *MockNotifier) RegisterConfirmationsNtfn(txid *chainhash.Hash,
	_ []byte, numConfs, heightHint uint32) (*chainntnfs.ConfirmationEvent,
	error)

RegisterConfirmationsNtfn registers for tx confirm notifications.

func (*MockNotifier) RegisterSpendNtfn

func (m *MockNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint,
	_ []byte, heightHint uint32) (*chainntnfs.SpendEvent, error)

RegisterSpendNtfn registers for spend notifications.

func (*MockNotifier) SpendOutpoint

func (m *MockNotifier) SpendOutpoint(outpoint wire.OutPoint,
	spendingTx wire.MsgTx)

SpendOutpoint simulates a utxo being spent.

func (*MockNotifier) Start

func (m *MockNotifier) Start() error

Start the notifier.

func (*MockNotifier) Started

func (m *MockNotifier) Started() bool

Started checks if started

func (*MockNotifier) Stop

func (m *MockNotifier) Stop() error

Stop the notifier.

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, error)

GetLastPublishedTx returns the last tx that we called NotifyPublishTx for.

func (*MockSweeperStore) IsOurTx

func (s *MockSweeperStore) IsOurTx(hash chainhash.Hash) (bool, error)

IsOurTx determines whether a tx is published by us, based on its hash.

func (*MockSweeperStore) ListSweeps

func (s *MockSweeperStore) ListSweeps() ([]chainhash.Hash, error)

ListSweeps lists all the sweeps we have successfully published.

func (*MockSweeperStore) NotifyPublishTx

func (s *MockSweeperStore) NotifyPublishTx(tx *wire.MsgTx) error

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.

func (Params) String

func (p Params) String() string

String returns a human readable interpretation of the sweep parameters.

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 eacutil.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 error

	// 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, error)

	// NotifyPublishTx signals that we are about to publish a tx.
	NotifyPublishTx(*wire.MsgTx) error

	// GetLastPublishedTx returns the last tx that we called NotifyPublishTx
	// for.
	GetLastPublishedTx() (*wire.MsgTx, error)

	// ListSweeps lists all the sweeps we have successfully published.
	ListSweeps() ([]chainhash.Hash, error)
}

SweeperStore stores published txes.

func NewSweeperStore

func NewSweeperStore(db kvdb.Backend, chainHash *chainhash.Hash) (
	SweeperStore, error)

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, error)
}

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 New

func New(cfg *UtxoSweeperConfig) *UtxoSweeper

New returns a new Sweeper instance.

func (*UtxoSweeper) CreateSweepTx

func (s *UtxoSweeper) CreateSweepTx(inputs []input.Input, feePref FeePreference,
	currentBlockHeight uint32) (*wire.MsgTx, error)

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, error)

ListSweeps returns a list of the the sweeps recorded by the sweep store.

func (*UtxoSweeper) PendingInputs

func (s *UtxoSweeper) PendingInputs() (map[wire.OutPoint]*PendingInput, error)

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() error

Start starts the process of constructing and publish sweep txes.

func (*UtxoSweeper) Stop

func (s *UtxoSweeper) Stop() error

Stop stops sweeper from listening to block epochs and constructing sweep txes.

func (*UtxoSweeper) SweepInput

func (s *UtxoSweeper) SweepInput(input input.Input,
	params Params) (chan Result, error)

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, error)

UpdateParams allows updating the sweep parameters of a pending input in the UtxoSweeper. This function can be used to provide an updated fee preference 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.

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, error)

	// 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) error

	// 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,
		error)

	// 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() error) error
}

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, blockHeight uint32,
	deliveryAddr eacutil.Address, coinSelectLocker CoinSelectionLocker,
	utxoSource UtxoSource, outpointLocker OutpointLocker,
	feeEstimator chainfee.Estimator,
	signer input.Signer) (*WalletSweepPackage, error)

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL