From b07e7b7cfda1f28ba0239fb8670516429e38f3d7 Mon Sep 17 00:00:00 2001 From: Boris Nagaev Date: Tue, 11 Feb 2025 11:23:17 -0300 Subject: [PATCH 1/3] bumpfee: use new fields instead of deprecated ones 'force' -> 'immediate' 'sat_per_byte' -> 'sat_per_vbyte' --- walletkit_client.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/walletkit_client.go b/walletkit_client.go index 3dfbef9..b008eea 100644 --- a/walletkit_client.go +++ b/walletkit_client.go @@ -755,8 +755,8 @@ func (m *walletKitClient) BumpFee(ctx context.Context, op wire.OutPoint, TxidBytes: op.Hash[:], OutputIndex: op.Index, }, - SatPerByte: uint32(feeRate.FeePerKVByte() / 1000), - Force: false, + SatPerVbyte: uint64(feeRate.FeePerKVByte() / 1000), + Immediate: false, }, ) return err From aa0e2861f209867de08434b904f56ff7267afb1c Mon Sep 17 00:00:00 2001 From: Boris Nagaev Date: Tue, 11 Feb 2025 11:46:55 -0300 Subject: [PATCH 2/3] bumpfee: add more flags as options New options added: 'immediate', 'target_conf', 'budget'. --- walletkit_client.go | 67 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 12 deletions(-) diff --git a/walletkit_client.go b/walletkit_client.go index b008eea..ebcbd73 100644 --- a/walletkit_client.go +++ b/walletkit_client.go @@ -134,7 +134,8 @@ type WalletKitClient interface { // child-pays-for-parent (CPFP) scenario. If the given output has been // used in a previous BumpFee call, then a transaction replacing the // previous is broadcast, resulting in a replace-by-fee (RBF) scenario. - BumpFee(context.Context, wire.OutPoint, chainfee.SatPerKWeight) error + BumpFee(context.Context, wire.OutPoint, chainfee.SatPerKWeight, + ...BumpFeeOption) error // ListAccounts retrieves all accounts belonging to the wallet by default. // Optional name and addressType can be provided to filter through all the @@ -737,28 +738,70 @@ func (m *walletKitClient) ListSweepsVerbose(ctx context.Context, return result, nil } +// BumpFeeOption customizes a BumpFee call. +type BumpFeeOption func(*walletrpc.BumpFeeRequest) + +// WithImmediate is an option for enabling the immediate mode of BumpFee. The +// sweeper will sweep this input without waiting for the next block. +func WithImmediate() BumpFeeOption { + return func(r *walletrpc.BumpFeeRequest) { + r.Immediate = true + } +} + +// WithTargetConf is an option for setting the target_conf of BumpFee. If set, +// the underlying fee estimator will use the target_conf to estimate the +// starting fee rate for the fee function. Pass feeRate=0 to BumpFee if you +// add this option. +func WithTargetConf(targetConf uint32) BumpFeeOption { + return func(r *walletrpc.BumpFeeRequest) { + r.TargetConf = targetConf + } +} + +// WithBudget is an option for setting the budget of BumpFee. It is the max +// amount in sats that can be used as the fees. Setting this value greater than +// the input's value may result in CPFP - one or more wallet utxos will be used +// to pay the fees specified by the budget. If not set, for new inputs, by +// default 50% of the input's value will be treated as the budget for fee +// bumping; for existing inputs, their current budgets will be retained. +func WithBudget(budget btcutil.Amount) BumpFeeOption { + return func(r *walletrpc.BumpFeeRequest) { + r.Budget = uint64(budget) + } +} + // BumpFee attempts to bump the fee of a transaction by spending one of its // outputs at the given fee rate. This essentially results in a // child-pays-for-parent (CPFP) scenario. If the given output has been used in a // previous BumpFee call, then a transaction replacing the previous is // broadcast, resulting in a replace-by-fee (RBF) scenario. func (m *walletKitClient) BumpFee(ctx context.Context, op wire.OutPoint, - feeRate chainfee.SatPerKWeight) error { + feeRate chainfee.SatPerKWeight, opts ...BumpFeeOption) error { rpcCtx, cancel := context.WithTimeout(ctx, m.timeout) defer cancel() - _, err := m.client.BumpFee( - m.walletKitMac.WithMacaroonAuth(rpcCtx), - &walletrpc.BumpFeeRequest{ - Outpoint: &lnrpc.OutPoint{ - TxidBytes: op.Hash[:], - OutputIndex: op.Index, - }, - SatPerVbyte: uint64(feeRate.FeePerKVByte() / 1000), - Immediate: false, + req := &walletrpc.BumpFeeRequest{ + Outpoint: &lnrpc.OutPoint{ + TxidBytes: op.Hash[:], + OutputIndex: op.Index, }, - ) + SatPerVbyte: uint64(feeRate.FeePerVByte()), + Immediate: false, + } + + for _, opt := range opts { + opt(req) + } + + // Make sure that feeRate and WithTargetConf are not used together. + if feeRate != 0 && req.TargetConf != 0 { + return fmt.Errorf("can't use target_conf if feeRate != 0") + } + + _, err := m.client.BumpFee(m.walletKitMac.WithMacaroonAuth(rpcCtx), req) + return err } From 41eb830631bcb25775d083447532f67e6521fa32 Mon Sep 17 00:00:00 2001 From: Boris Nagaev Date: Sat, 15 Feb 2025 11:46:59 -0300 Subject: [PATCH 3/3] bumpfee: check LND>=0.18.5 if target_conf is used The conf-target only reflects this behaviour for the 0.18.5 release, before the conf target had a different meaning: https://github.com/lightningnetwork/lnd/pull/9470 This commit can be undone after minimalCompatibleVersion is bumbed to 0.18.5. --- lnd_services.go | 1 + walletkit_client.go | 28 +++++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lnd_services.go b/lnd_services.go index 979b98d..6a0c207 100644 --- a/lnd_services.go +++ b/lnd_services.go @@ -372,6 +372,7 @@ func NewLndServices(cfg *LndServicesConfig) (*GrpcLndServices, error) { ) walletKitClient := newWalletKitClient( conn, macaroons[WalletKitServiceMac], timeout, chainParams, + version, ) invoicesClient := newInvoicesClient( conn, macaroons[InvoiceServiceMac], timeout, diff --git a/walletkit_client.go b/walletkit_client.go index ebcbd73..148c748 100644 --- a/walletkit_client.go +++ b/walletkit_client.go @@ -20,6 +20,7 @@ import ( "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc/signrpc" + "github.com/lightningnetwork/lnd/lnrpc/verrpc" "github.com/lightningnetwork/lnd/lnrpc/walletrpc" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" @@ -219,6 +220,7 @@ type walletKitClient struct { walletKitMac serializedMacaroon timeout time.Duration params *chaincfg.Params + version *verrpc.Version } // A compile time check to ensure that walletKitClient implements the @@ -227,13 +229,15 @@ var _ WalletKitClient = (*walletKitClient)(nil) func newWalletKitClient(conn grpc.ClientConnInterface, walletKitMac serializedMacaroon, timeout time.Duration, - chainParams *chaincfg.Params) *walletKitClient { + chainParams *chaincfg.Params, + version *verrpc.Version) *walletKitClient { return &walletKitClient{ client: walletrpc.NewWalletKitClient(conn), walletKitMac: walletKitMac, timeout: timeout, params: chainParams, + version: version, } } @@ -771,6 +775,15 @@ func WithBudget(budget btcutil.Amount) BumpFeeOption { } } +// targetConfFixed is the minimum version in which bug #9470 is merged and new +// meaning of TargetConf is enabled. In versions prior to this version the field +// had a different meaning. +var targetConfFixed = &verrpc.Version{ + AppMajor: 0, + AppMinor: 18, + AppPatch: 5, +} + // BumpFee attempts to bump the fee of a transaction by spending one of its // outputs at the given fee rate. This essentially results in a // child-pays-for-parent (CPFP) scenario. If the given output has been used in a @@ -800,6 +813,19 @@ func (m *walletKitClient) BumpFee(ctx context.Context, op wire.OutPoint, return fmt.Errorf("can't use target_conf if feeRate != 0") } + // Make sure that the version of LND is at least targetConfFixed, + // because before it the meaning of TargetConf was different. See + // https://github.com/lightningnetwork/lnd/pull/9470 + // TODO(Boris): remove this check when minimalCompatibleVersion + // is bumped to targetConfFixed. + if req.TargetConf != 0 { + err := AssertVersionCompatible(m.version, targetConfFixed) + if err != nil { + return fmt.Errorf("can't use target_conf before " + + "version 0.18.5, see #9470") + } + } + _, err := m.client.BumpFee(m.walletKitMac.WithMacaroonAuth(rpcCtx), req) return err