sweep: add wallet inputs to reach dust limit

This commit allows sweeper to sweep inputs that on its own are not able
to form a sweep transaction that meets the dust limit.

This functionality is useful for sweeping small outputs. In the future,
this will be particularly important to sweep anchors. Anchors will
typically be spent with a relatively large fee to pay for the parent tx.
It will then be necessary to attach an additional wallet utxo.
This commit is contained in:
Joost Jager
2019-12-10 16:06:45 +01:00
parent 8353b6fd6e
commit e01600fdb8
7 changed files with 299 additions and 34 deletions

View File

@ -5,6 +5,7 @@ import (
"github.com/btcsuite/btcutil"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lnwallet"
)
// TestTxInputSet tests adding various sized inputs to the set.
@ -14,7 +15,7 @@ func TestTxInputSet(t *testing.T) {
relayFee = 300
maxInputs = 10
)
set := newTxInputSet(feeRate, relayFee, maxInputs)
set := newTxInputSet(nil, feeRate, relayFee, maxInputs)
if set.dustLimit != 537 {
t.Fatalf("incorrect dust limit")
@ -23,13 +24,13 @@ func TestTxInputSet(t *testing.T) {
// Create a 300 sat input. The fee to sweep this input to a P2WKH output
// is 439 sats. That means that this input yields -139 sats and we
// expect it not to be added.
if set.add(createP2WKHInput(300)) {
if set.add(createP2WKHInput(300), false) {
t.Fatal("expected add of negatively yielding input to fail")
}
// A 700 sat input should be accepted into the set, because it yields
// positively.
if !set.add(createP2WKHInput(700)) {
if !set.add(createP2WKHInput(700), false) {
t.Fatal("expected add of positively yielding input to succeed")
}
@ -44,7 +45,7 @@ func TestTxInputSet(t *testing.T) {
// Add a 1000 sat input. This increases the tx fee to 712 sats. The tx
// output should now be 1000+700 - 712 = 988 sats.
if !set.add(createP2WKHInput(1000)) {
if !set.add(createP2WKHInput(1000), false) {
t.Fatal("expected add of positively yielding input to succeed")
}
if set.outputValue != 988 {
@ -55,8 +56,54 @@ func TestTxInputSet(t *testing.T) {
}
}
// TestTxInputSetFromWallet tests adding a wallet input to a TxInputSet to reach
// the dust limit.
func TestTxInputSetFromWallet(t *testing.T) {
const (
feeRate = 500
relayFee = 300
maxInputs = 10
)
wallet := &mockWallet{}
set := newTxInputSet(wallet, feeRate, relayFee, maxInputs)
// Add a 700 sat input to the set. It yields positively, but doesn't
// reach the output dust limit.
if !set.add(createP2WKHInput(700), false) {
t.Fatal("expected add of positively yielding input to succeed")
}
if set.dustLimitReached() {
t.Fatal("expected dust limit not yet to be reached")
}
err := set.tryAddWalletInputsIfNeeded()
if err != nil {
t.Fatal(err)
}
if !set.dustLimitReached() {
t.Fatal("expected dust limit to be reached")
}
}
// createP2WKHInput returns a P2WKH test input with the specified amount.
func createP2WKHInput(amt btcutil.Amount) input.Input {
input := createTestInput(int64(amt), input.WitnessKeyHash)
return &input
}
type mockWallet struct {
Wallet
}
func (m *mockWallet) ListUnspentWitness(minconfirms, maxconfirms int32) (
[]*lnwallet.Utxo, error) {
return []*lnwallet.Utxo{
{
AddressType: lnwallet.WitnessPubKey,
Value: 10000,
},
}, nil
}