From 2cc5891c8c6c367e9e83ffca41a8340234267a31 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Wed, 21 Aug 2019 17:24:07 -0700 Subject: [PATCH] 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. --- lnrpc/walletrpc/config_active.go | 4 ++++ lnrpc/walletrpc/driver.go | 8 ++++++++ lnrpc/walletrpc/walletkit_server.go | 17 ++++++++++++++++- subrpcserver_config.go | 3 +++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/lnrpc/walletrpc/config_active.go b/lnrpc/walletrpc/config_active.go index 77dc0e57..9804bc11 100644 --- a/lnrpc/walletrpc/config_active.go +++ b/lnrpc/walletrpc/config_active.go @@ -43,4 +43,8 @@ type Config struct { // Sweeper is the central batching engine of lnd. It is responsible for // sweeping inputs in batches back into the wallet. 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 } diff --git a/lnrpc/walletrpc/driver.go b/lnrpc/walletrpc/driver.go index 4135d3aa..deb02a6e 100644 --- a/lnrpc/walletrpc/driver.go +++ b/lnrpc/walletrpc/driver.go @@ -51,6 +51,14 @@ func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (lnrpc.S case config.KeyRing == nil: return nil, nil, fmt.Errorf("KeyRing must be set to create " + "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) diff --git a/lnrpc/walletrpc/walletkit_server.go b/lnrpc/walletrpc/walletkit_server.go index 374983f4..b463774e 100644 --- a/lnrpc/walletrpc/walletkit_server.go +++ b/lnrpc/walletrpc/walletkit_server.go @@ -4,6 +4,7 @@ package walletrpc import ( "bytes" + "errors" "fmt" "io/ioutil" "os" @@ -501,6 +502,12 @@ func (w *WalletKit) BumpFee(ctx context.Context, 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 switch utxo.AddressType { case lnwallet.WitnessPubKey: @@ -519,7 +526,15 @@ func (w *WalletKit) BumpFee(ctx context.Context, 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 { return nil, err } diff --git a/subrpcserver_config.go b/subrpcserver_config.go index 06b9dfc5..d00e3a43 100644 --- a/subrpcserver_config.go +++ b/subrpcserver_config.go @@ -152,6 +152,9 @@ func (s *subRPCServerConfigs) PopulateDependencies(cc *chainControl, subCfgValue.FieldByName("Sweeper").Set( reflect.ValueOf(sweeper), ) + subCfgValue.FieldByName("Chain").Set( + reflect.ValueOf(cc.chainIO), + ) case *autopilotrpc.Config: subCfgValue := extractReflectValue(subCfg)