lnrpc/walletrpc: use current height as height hint for cpfp

In this commit, we address an issue that would cause us to scan from the
genesis block for the spend of an output that we wish to use to raise
the fee of a transaction through CPFP. This was due to setting a 0
height hint when constructing the input required by the sweeper and was
discovered due to the recently added validation checks at the chain
notifier level. We'll now use the current height as the height hint
instead as the sweeper will end up creating a new transaction that
spends the input.
This commit is contained in:
Wilmer Paulino 2019-08-21 17:24:07 -07:00
parent 9e8a1707cc
commit 2cc5891c8c
No known key found for this signature in database
GPG Key ID: 6DF57B9F9514972F
4 changed files with 31 additions and 1 deletions

@ -43,4 +43,8 @@ type Config struct {
// Sweeper is the central batching engine of lnd. It is responsible for // Sweeper is the central batching engine of lnd. It is responsible for
// sweeping inputs in batches back into the wallet. // sweeping inputs in batches back into the wallet.
Sweeper *sweep.UtxoSweeper Sweeper *sweep.UtxoSweeper
// Chain is an interface that the WalletKit will use to determine state
// about the backing chain of the wallet.
Chain lnwallet.BlockChainIO
} }

@ -51,6 +51,14 @@ func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (lnrpc.S
case config.KeyRing == nil: case config.KeyRing == nil:
return nil, nil, fmt.Errorf("KeyRing must be set to create " + return nil, nil, fmt.Errorf("KeyRing must be set to create " +
"WalletKit RPC server") "WalletKit RPC server")
case config.Sweeper == nil:
return nil, nil, fmt.Errorf("Sweeper must be set to create " +
"WalletKit RPC server")
case config.Chain == nil:
return nil, nil, fmt.Errorf("Chain must be set to create " +
"WalletKit RPC server")
} }
return New(config) return New(config)

@ -4,6 +4,7 @@ package walletrpc
import ( import (
"bytes" "bytes"
"errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
@ -501,6 +502,12 @@ func (w *WalletKit) BumpFee(ctx context.Context,
return nil, err return nil, err
} }
// We're only able to bump the fee of unconfirmed transactions.
if utxo.Confirmations > 0 {
return nil, errors.New("unable to bump fee of a confirmed " +
"transaction")
}
var witnessType input.WitnessType var witnessType input.WitnessType
switch utxo.AddressType { switch utxo.AddressType {
case lnwallet.WitnessPubKey: case lnwallet.WitnessPubKey:
@ -519,7 +526,15 @@ func (w *WalletKit) BumpFee(ctx context.Context,
HashType: txscript.SigHashAll, HashType: txscript.SigHashAll,
} }
input := input.NewBaseInput(op, witnessType, signDesc, 0) // We'll use the current height as the height hint since we're dealing
// with an unconfirmed transaction.
_, currentHeight, err := w.cfg.Chain.GetBestBlock()
if err != nil {
return nil, fmt.Errorf("unable to retrieve current height: %v",
err)
}
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, feePreference); err != nil {
return nil, err return nil, err
} }

@ -152,6 +152,9 @@ func (s *subRPCServerConfigs) PopulateDependencies(cc *chainControl,
subCfgValue.FieldByName("Sweeper").Set( subCfgValue.FieldByName("Sweeper").Set(
reflect.ValueOf(sweeper), reflect.ValueOf(sweeper),
) )
subCfgValue.FieldByName("Chain").Set(
reflect.ValueOf(cc.chainIO),
)
case *autopilotrpc.Config: case *autopilotrpc.Config:
subCfgValue := extractReflectValue(subCfg) subCfgValue := extractReflectValue(subCfg)