mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-11-10 22:27:22 +01:00
cmd: update bumpfee, bumpclosefee and bumpforceclosefee
This commit is contained in:
@@ -177,56 +177,78 @@ var bumpFeeCommand = cli.Command{
|
|||||||
Usage: "Bumps the fee of an arbitrary input/transaction.",
|
Usage: "Bumps the fee of an arbitrary input/transaction.",
|
||||||
ArgsUsage: "outpoint",
|
ArgsUsage: "outpoint",
|
||||||
Description: `
|
Description: `
|
||||||
This command takes a different approach than bitcoind's bumpfee command.
|
BumpFee is an endpoint that allows users to interact with lnd's sweeper
|
||||||
lnd has a central batching engine in which inputs with similar fee rates
|
directly. It takes an outpoint from an unconfirmed transaction and
|
||||||
are batched together to save on transaction fees. Due to this, we cannot
|
sends it to the sweeper for potential fee bumping. Depending on whether
|
||||||
rely on bumping the fee on a specific transaction, since transactions
|
the outpoint has been registered in the sweeper (an existing input,
|
||||||
can change at any point with the addition of new inputs. The list of
|
e.g., an anchor output) or not (a new input, e.g., an unconfirmed
|
||||||
inputs that currently exist within lnd's central batching engine can be
|
wallet utxo), this will either be an RBF or CPFP attempt.
|
||||||
retrieved through lncli wallet pendingsweeps.
|
|
||||||
|
|
||||||
When bumping the fee of an input that currently exists within lnd's
|
When receiving an input, lnd’s sweeper needs to understand its time
|
||||||
central batching engine, a higher fee transaction will be created that
|
sensitivity to make economical fee bumps - internally a fee function is
|
||||||
replaces the lower fee transaction through the Replace-By-Fee (RBF)
|
created using the deadline and budget to guide the process. When the
|
||||||
policy.
|
deadline is approaching, the fee function will increase the fee rate
|
||||||
|
and perform an RBF.
|
||||||
|
|
||||||
This command also serves useful when wanting to perform a
|
When a force close happens, all the outputs from the force closing
|
||||||
|
transaction will be registered in the sweeper. The sweeper will then
|
||||||
|
handle the creation, publish, and fee bumping of the sweeping
|
||||||
|
transactions. Everytime a new block comes in, unless the sweeping
|
||||||
|
transaction is confirmed, an RBF is attempted. To interfere with this
|
||||||
|
automatic process, users can use BumpFee to specify customized fee
|
||||||
|
rate, budget, deadline, and whether the sweep should happen
|
||||||
|
immediately. It's recommended to call listsweeps to understand the
|
||||||
|
shape of the existing sweeping transaction first - depending on the
|
||||||
|
number of inputs in this transaction, the RBF requirements can be quite
|
||||||
|
different.
|
||||||
|
|
||||||
|
This RPC also serves useful when wanting to perform a
|
||||||
Child-Pays-For-Parent (CPFP), where the child transaction pays for its
|
Child-Pays-For-Parent (CPFP), where the child transaction pays for its
|
||||||
parent's fee. This can be done by specifying an outpoint within the low
|
parent's fee. This can be done by specifying an outpoint within the low
|
||||||
fee transaction that is under the control of the wallet.
|
fee transaction that is under the control of the wallet.
|
||||||
|
|
||||||
A fee preference must be provided, either through the conf_target or
|
|
||||||
sat_per_vbyte parameters.
|
|
||||||
|
|
||||||
Note that this command currently doesn't perform any validation checks
|
|
||||||
on the fee preference being provided. For now, the responsibility of
|
|
||||||
ensuring that the new fee preference is sufficient is delegated to the
|
|
||||||
user.
|
|
||||||
|
|
||||||
The force flag enables sweeping of inputs that are negatively yielding.
|
|
||||||
Normally it does not make sense to lose money on sweeping, unless a
|
|
||||||
parent transaction needs to get confirmed and there is only a small
|
|
||||||
output available to attach the child transaction to.
|
|
||||||
`,
|
`,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.Uint64Flag{
|
cli.Uint64Flag{
|
||||||
Name: "conf_target",
|
Name: "conf_target",
|
||||||
Usage: "the number of blocks that the output should " +
|
Usage: `
|
||||||
"be swept on-chain within",
|
The deadline in number of blocks that the input should be spent within.
|
||||||
|
When not set, for new inputs, the default value (1008) is used; for
|
||||||
|
exiting inputs, their current values will be retained.`,
|
||||||
},
|
},
|
||||||
cli.Uint64Flag{
|
cli.Uint64Flag{
|
||||||
Name: "sat_per_byte",
|
Name: "sat_per_byte",
|
||||||
Usage: "Deprecated, use sat_per_vbyte instead.",
|
Usage: "Deprecated, use sat_per_vbyte instead.",
|
||||||
Hidden: true,
|
Hidden: true,
|
||||||
},
|
},
|
||||||
cli.Uint64Flag{
|
|
||||||
Name: "sat_per_vbyte",
|
|
||||||
Usage: "a manual fee expressed in sat/vbyte that " +
|
|
||||||
"should be used when sweeping the output",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "force",
|
Name: "force",
|
||||||
Usage: "sweep even if the yield is negative",
|
Usage: "Deprecated, use immediate instead.",
|
||||||
|
Hidden: true,
|
||||||
|
},
|
||||||
|
cli.Uint64Flag{
|
||||||
|
Name: "sat_per_vbyte",
|
||||||
|
Usage: `
|
||||||
|
The starting fee rate, expressed in sat/vbyte, that will be used to
|
||||||
|
spend the input with initially. This value will be used by the
|
||||||
|
sweeper's fee function as its starting fee rate. When not set, the
|
||||||
|
sweeper will use the estimated fee rate using the target_conf as the
|
||||||
|
starting fee rate.`,
|
||||||
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "immediate",
|
||||||
|
Usage: `
|
||||||
|
Whether this input will be swept immediately. When set to true, the
|
||||||
|
sweeper will sweep this input without waiting for the next batch.`,
|
||||||
|
},
|
||||||
|
cli.Uint64Flag{
|
||||||
|
Name: "budget",
|
||||||
|
Usage: `
|
||||||
|
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.`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Action: actionDecorator(bumpFee),
|
Action: actionDecorator(bumpFee),
|
||||||
@@ -241,15 +263,6 @@ func bumpFee(ctx *cli.Context) error {
|
|||||||
return cli.ShowCommandHelp(ctx, "bumpfee")
|
return cli.ShowCommandHelp(ctx, "bumpfee")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that only the field sat_per_vbyte or the deprecated field
|
|
||||||
// sat_per_byte is used.
|
|
||||||
feeRateFlag, err := checkNotBothSet(
|
|
||||||
ctx, "sat_per_vbyte", "sat_per_byte",
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate and parse the relevant arguments/flags.
|
// Validate and parse the relevant arguments/flags.
|
||||||
protoOutPoint, err := NewProtoOutPoint(ctx.Args().Get(0))
|
protoOutPoint, err := NewProtoOutPoint(ctx.Args().Get(0))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -262,8 +275,8 @@ func bumpFee(ctx *cli.Context) error {
|
|||||||
resp, err := client.BumpFee(ctxc, &walletrpc.BumpFeeRequest{
|
resp, err := client.BumpFee(ctxc, &walletrpc.BumpFeeRequest{
|
||||||
Outpoint: protoOutPoint,
|
Outpoint: protoOutPoint,
|
||||||
TargetConf: uint32(ctx.Uint64("conf_target")),
|
TargetConf: uint32(ctx.Uint64("conf_target")),
|
||||||
SatPerVbyte: ctx.Uint64(feeRateFlag),
|
Immediate: ctx.Bool("force"),
|
||||||
Force: ctx.Bool("force"),
|
Budget: ctx.Uint64("budget"),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -291,18 +304,45 @@ var bumpCloseFeeCommand = cli.Command{
|
|||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.Uint64Flag{
|
cli.Uint64Flag{
|
||||||
Name: "conf_target",
|
Name: "conf_target",
|
||||||
Usage: "the number of blocks that the output should " +
|
Usage: `
|
||||||
"be swept on-chain within",
|
The deadline in number of blocks that the input should be spent within.
|
||||||
|
When not set, for new inputs, the default value (1008) is used; for
|
||||||
|
exiting inputs, their current values will be retained.`,
|
||||||
},
|
},
|
||||||
cli.Uint64Flag{
|
cli.Uint64Flag{
|
||||||
Name: "sat_per_byte",
|
Name: "sat_per_byte",
|
||||||
Usage: "Deprecated, use sat_per_vbyte instead.",
|
Usage: "Deprecated, use sat_per_vbyte instead.",
|
||||||
Hidden: true,
|
Hidden: true,
|
||||||
},
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "force",
|
||||||
|
Usage: "Deprecated, use immediate instead.",
|
||||||
|
Hidden: true,
|
||||||
|
},
|
||||||
cli.Uint64Flag{
|
cli.Uint64Flag{
|
||||||
Name: "sat_per_vbyte",
|
Name: "sat_per_vbyte",
|
||||||
Usage: "a manual fee expressed in sat/vbyte that " +
|
Usage: `
|
||||||
"should be used when sweeping the output",
|
The starting fee rate, expressed in sat/vbyte, that will be used to
|
||||||
|
spend the input with initially. This value will be used by the
|
||||||
|
sweeper's fee function as its starting fee rate. When not set, the
|
||||||
|
sweeper will use the estimated fee rate using the target_conf as the
|
||||||
|
starting fee rate.`,
|
||||||
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "immediate",
|
||||||
|
Usage: `
|
||||||
|
Whether this input will be swept immediately. When set to true, the
|
||||||
|
sweeper will sweep this input without waiting for the next batch.`,
|
||||||
|
},
|
||||||
|
cli.Uint64Flag{
|
||||||
|
Name: "budget",
|
||||||
|
Usage: `
|
||||||
|
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.`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Action: actionDecorator(bumpForceCloseFee),
|
Action: actionDecorator(bumpForceCloseFee),
|
||||||
@@ -323,18 +363,45 @@ var bumpForceCloseFeeCommand = cli.Command{
|
|||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.Uint64Flag{
|
cli.Uint64Flag{
|
||||||
Name: "conf_target",
|
Name: "conf_target",
|
||||||
Usage: "the number of blocks that the output should " +
|
Usage: `
|
||||||
"be swept on-chain within",
|
The deadline in number of blocks that the input should be spent within.
|
||||||
|
When not set, for new inputs, the default value (1008) is used; for
|
||||||
|
exiting inputs, their current values will be retained.`,
|
||||||
},
|
},
|
||||||
cli.Uint64Flag{
|
cli.Uint64Flag{
|
||||||
Name: "sat_per_byte",
|
Name: "sat_per_byte",
|
||||||
Usage: "Deprecated, use sat_per_vbyte instead.",
|
Usage: "Deprecated, use sat_per_vbyte instead.",
|
||||||
Hidden: true,
|
Hidden: true,
|
||||||
},
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "force",
|
||||||
|
Usage: "Deprecated, use immediate instead.",
|
||||||
|
Hidden: true,
|
||||||
|
},
|
||||||
cli.Uint64Flag{
|
cli.Uint64Flag{
|
||||||
Name: "sat_per_vbyte",
|
Name: "sat_per_vbyte",
|
||||||
Usage: "a manual fee expressed in sat/vbyte that " +
|
Usage: `
|
||||||
"should be used when sweeping the output",
|
The starting fee rate, expressed in sat/vbyte, that will be used to
|
||||||
|
spend the input with initially. This value will be used by the
|
||||||
|
sweeper's fee function as its starting fee rate. When not set, the
|
||||||
|
sweeper will use the estimated fee rate using the target_conf as the
|
||||||
|
starting fee rate.`,
|
||||||
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "immediate",
|
||||||
|
Usage: `
|
||||||
|
Whether this input will be swept immediately. When set to true, the
|
||||||
|
sweeper will sweep this input without waiting for the next batch.`,
|
||||||
|
},
|
||||||
|
cli.Uint64Flag{
|
||||||
|
Name: "budget",
|
||||||
|
Usage: `
|
||||||
|
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.`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Action: actionDecorator(bumpForceCloseFee),
|
Action: actionDecorator(bumpForceCloseFee),
|
||||||
@@ -349,18 +416,9 @@ func bumpForceCloseFee(ctx *cli.Context) error {
|
|||||||
return cli.ShowCommandHelp(ctx, "bumpclosefee")
|
return cli.ShowCommandHelp(ctx, "bumpclosefee")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that only the field sat_per_vbyte or the deprecated field
|
|
||||||
// sat_per_byte is used.
|
|
||||||
feeRateFlag, err := checkNotBothSet(
|
|
||||||
ctx, "sat_per_vbyte", "sat_per_byte",
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate the channel point.
|
// Validate the channel point.
|
||||||
channelPoint := ctx.Args().Get(0)
|
channelPoint := ctx.Args().Get(0)
|
||||||
_, err = NewProtoOutPoint(channelPoint)
|
_, err := NewProtoOutPoint(channelPoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -417,8 +475,8 @@ func bumpForceCloseFee(ctx *cli.Context) error {
|
|||||||
ctxc, &walletrpc.BumpFeeRequest{
|
ctxc, &walletrpc.BumpFeeRequest{
|
||||||
Outpoint: sweep.Outpoint,
|
Outpoint: sweep.Outpoint,
|
||||||
TargetConf: uint32(ctx.Uint64("conf_target")),
|
TargetConf: uint32(ctx.Uint64("conf_target")),
|
||||||
SatPerVbyte: ctx.Uint64(feeRateFlag),
|
Budget: ctx.Uint64("budget"),
|
||||||
Force: true,
|
Immediate: ctx.Bool("immediate"),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
Reference in New Issue
Block a user