Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sweep: add wallet inputs to reach dust limit #3814

Merged
merged 9 commits into from
Dec 18, 2019
7 changes: 6 additions & 1 deletion chainregistry.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ const (
// expressed in sat/kw.
defaultBitcoinStaticFeePerKW = chainfee.SatPerKWeight(12500)

// defaultBitcoinStaticMinRelayFeeRate is the min relay fee used for
// static estimators.
defaultBitcoinStaticMinRelayFeeRate = chainfee.FeePerKwFloor

// defaultLitecoinStaticFeePerKW is the fee rate of 200 sat/vbyte
// expressed in sat/kw.
defaultLitecoinStaticFeePerKW = chainfee.SatPerKWeight(50000)
Expand Down Expand Up @@ -163,7 +167,8 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
TimeLockDelta: cfg.Bitcoin.TimeLockDelta,
}
cc.feeEstimator = chainfee.NewStaticEstimator(
defaultBitcoinStaticFeePerKW, 0,
defaultBitcoinStaticFeePerKW,
defaultBitcoinStaticMinRelayFeeRate,
)
case litecoinChain:
cc.routingPolicy = htlcswitch.ForwardingPolicy{
Expand Down
2 changes: 1 addition & 1 deletion contractcourt/commit_sweep_resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ func (c *commitSweepResolver) Resolve() (ContractResolver, error) {
c.log.Infof("sweeping commit output")

feePref := sweep.FeePreference{ConfTarget: commitOutputConfTarget}
resultChan, err := c.Sweeper.SweepInput(inp, feePref)
resultChan, err := c.Sweeper.SweepInput(inp, sweep.Params{Fee: feePref})
if err != nil {
c.log.Errorf("unable to sweep input: %v", err)

Expand Down
4 changes: 2 additions & 2 deletions contractcourt/commit_sweep_resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ func newMockSweeper() *mockSweeper {
}
}

func (s *mockSweeper) SweepInput(input input.Input,
feePreference sweep.FeePreference) (chan sweep.Result, error) {
func (s *mockSweeper) SweepInput(input input.Input, params sweep.Params) (
chan sweep.Result, error) {

s.sweptInputs <- input

Expand Down
4 changes: 2 additions & 2 deletions contractcourt/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ type OnionProcessor interface {
// UtxoSweeper defines the sweep functions that contract court requires.
type UtxoSweeper interface {
// SweepInput sweeps inputs back into the wallet.
SweepInput(input input.Input,
feePreference sweep.FeePreference) (chan sweep.Result, error)
SweepInput(input input.Input, params sweep.Params) (chan sweep.Result,
error)

// CreateSweepTx accepts a list of inputs and signs and generates a txn
// that spends from them. This method also makes an accurate fee
Expand Down
2 changes: 1 addition & 1 deletion lnrpc/walletrpc/walletkit_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ func (w *WalletKit) BumpFee(ctx context.Context,
}

input := input.NewBaseInput(op, witnessType, signDesc, uint32(currentHeight))
if _, err = w.cfg.Sweeper.SweepInput(input, feePreference); err != nil {
if _, err = w.cfg.Sweeper.SweepInput(input, sweep.Params{Fee: feePreference}); err != nil {
return nil, err
}

Expand Down
8 changes: 4 additions & 4 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -792,10 +792,10 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB,
}

s.sweeper = sweep.New(&sweep.UtxoSweeperConfig{
FeeEstimator: cc.feeEstimator,
GenSweepScript: newSweepPkScriptGen(cc.wallet),
Signer: cc.wallet.Cfg.Signer,
PublishTransaction: cc.wallet.PublishTransaction,
FeeEstimator: cc.feeEstimator,
GenSweepScript: newSweepPkScriptGen(cc.wallet),
Signer: cc.wallet.Cfg.Signer,
Wallet: cc.wallet,
NewBatchTimer: func() <-chan time.Time {
return time.NewTimer(sweep.DefaultBatchWindowDuration).C
},
Expand Down
33 changes: 32 additions & 1 deletion sweep/backend_mock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package sweep

import (
"sync"
"testing"
"time"

"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
Expand All @@ -11,6 +13,8 @@ import (
// mockBackend simulates a chain backend for realistic behaviour in unit tests
// around double spends.
type mockBackend struct {
t *testing.T

lock sync.Mutex

notifier *MockNotifier
Expand All @@ -19,14 +23,20 @@ type mockBackend struct {

unconfirmedTxes map[chainhash.Hash]*wire.MsgTx
unconfirmedSpendInputs map[wire.OutPoint]struct{}

publishChan chan wire.MsgTx

walletUtxos []*lnwallet.Utxo
}

func newMockBackend(notifier *MockNotifier) *mockBackend {
func newMockBackend(t *testing.T, notifier *MockNotifier) *mockBackend {
return &mockBackend{
t: t,
notifier: notifier,
unconfirmedTxes: make(map[chainhash.Hash]*wire.MsgTx),
confirmedSpendInputs: make(map[wire.OutPoint]struct{}),
unconfirmedSpendInputs: make(map[wire.OutPoint]struct{}),
publishChan: make(chan wire.MsgTx, 2),
}
}

Expand Down Expand Up @@ -65,6 +75,27 @@ func (b *mockBackend) publishTransaction(tx *wire.MsgTx) error {
return nil
}

func (b *mockBackend) PublishTransaction(tx *wire.MsgTx) error {
log.Tracef("Publishing tx %v", tx.TxHash())
err := b.publishTransaction(tx)
select {
case b.publishChan <- *tx:
case <-time.After(defaultTestTimeout):
b.t.Fatalf("unexpected tx published")
}
return err
}

func (b *mockBackend) ListUnspentWitness(minconfirms, maxconfirms int32) (
[]*lnwallet.Utxo, error) {

return b.walletUtxos, nil
}

func (b *mockBackend) WithCoinSelectLock(f func() error) error {
return f()
}

func (b *mockBackend) deleteUnconfirmed(txHash chainhash.Hash) {
b.lock.Lock()
defer b.lock.Unlock()
Expand Down
27 changes: 27 additions & 0 deletions sweep/interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package sweep

import (
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/lnwallet"
)

// Wallet contains all wallet related functionality required by sweeper.
type Wallet interface {
joostjager marked this conversation as resolved.
Show resolved Hide resolved
// PublishTransaction performs cursory validation (dust checks, etc) and
// broadcasts the passed transaction to the Bitcoin network.
PublishTransaction(tx *wire.MsgTx) 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 if executing. This can be seen as the
// ability to execute a function closure under an exclusive coin
// selection lock.
WithCoinSelectLock(f func() error) error
}
Loading