mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-19 06:43:45 +01:00
Merge #18654: rpc: separate bumpfee's psbt creation function into psbtbumpfee
79d6332e9emoveonly: Fix indentation in bumpfee RPC (Andrew Chow)431071c28aHide bumpfee's psbt creation behavior behind -deprecatedrpc (Andrew Chow)4638224f64Add psbtbumpfee RPC (Andrew Chow) Pull request description: Adds a new RPC `psbtbumpfee` which always creates a psbt. `bumpfee` will then only be able to create and broadcast fee bumping transactions instead of changing its behavior based on `IsWalletSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)`. Split from #18627 ACKs for top commit: Sjors: re-utACK79d6332meshcollider: utACK79d6332e9efjahr: Code review ACK79d6332e9eTree-SHA512: 1c92c4b4461bb30e78be3ee73165f624398ef33996ce36043b61a8931be667030d0fca12fd0b30097b78c56e4e9092c69582b237cbdac51d56f6be23d8c0f1bb
This commit is contained in:
@@ -3222,59 +3222,73 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
|
||||
|
||||
static UniValue bumpfee(const JSONRPCRequest& request)
|
||||
{
|
||||
RPCHelpMan{"bumpfee",
|
||||
"\nBumps the fee of an opt-in-RBF transaction T, replacing it with a new transaction B.\n"
|
||||
"An opt-in RBF transaction with the given txid must be in the wallet.\n"
|
||||
"The command will pay the additional fee by reducing change outputs or adding inputs when necessary. It may add a new change output if one does not already exist.\n"
|
||||
"All inputs in the original transaction will be included in the replacement transaction.\n"
|
||||
"The command will fail if the wallet or mempool contains a transaction that spends one of T's outputs.\n"
|
||||
"By default, the new fee will be calculated automatically using estimatesmartfee.\n"
|
||||
"The user can specify a confirmation target for estimatesmartfee.\n"
|
||||
"Alternatively, the user can specify a fee_rate (" + CURRENCY_UNIT + " per kB) for the new transaction.\n"
|
||||
"At a minimum, the new fee rate must be high enough to pay an additional new relay fee (incrementalfee\n"
|
||||
"returned by getnetworkinfo) to enter the node's mempool.\n",
|
||||
bool want_psbt = request.strMethod == "psbtbumpfee";
|
||||
|
||||
RPCHelpMan{request.strMethod,
|
||||
"\nBumps the fee of an opt-in-RBF transaction T, replacing it with a new transaction B.\n"
|
||||
+ std::string(want_psbt ? "Returns a PSBT instead of creating and signing a new transaction.\n" : "") +
|
||||
"An opt-in RBF transaction with the given txid must be in the wallet.\n"
|
||||
"The command will pay the additional fee by reducing change outputs or adding inputs when necessary. It may add a new change output if one does not already exist.\n"
|
||||
"All inputs in the original transaction will be included in the replacement transaction.\n"
|
||||
"The command will fail if the wallet or mempool contains a transaction that spends one of T's outputs.\n"
|
||||
"By default, the new fee will be calculated automatically using estimatesmartfee.\n"
|
||||
"The user can specify a confirmation target for estimatesmartfee.\n"
|
||||
"Alternatively, the user can specify a fee_rate (" + CURRENCY_UNIT + " per kB) for the new transaction.\n"
|
||||
"At a minimum, the new fee rate must be high enough to pay an additional new relay fee (incrementalfee\n"
|
||||
"returned by getnetworkinfo) to enter the node's mempool.\n",
|
||||
{
|
||||
{"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The txid to be bumped"},
|
||||
{"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "",
|
||||
{
|
||||
{"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The txid to be bumped"},
|
||||
{"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "",
|
||||
{
|
||||
{"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks)"},
|
||||
{"fee_rate", RPCArg::Type::NUM, /* default */ "fall back to 'conf_target'", "fee rate (NOT total fee) to pay, in " + CURRENCY_UNIT + " per kB\n"
|
||||
" Specify a fee rate instead of relying on the built-in fee estimator.\n"
|
||||
"Must be at least 0.0001 " + CURRENCY_UNIT + " per kB higher than the current transaction fee rate.\n"},
|
||||
{"replaceable", RPCArg::Type::BOOL, /* default */ "true", "Whether the new transaction should still be\n"
|
||||
" marked bip-125 replaceable. If true, the sequence numbers in the transaction will\n"
|
||||
" be left unchanged from the original. If false, any input sequence numbers in the\n"
|
||||
" original transaction that were less than 0xfffffffe will be increased to 0xfffffffe\n"
|
||||
" so the new transaction will not be explicitly bip-125 replaceable (though it may\n"
|
||||
" still be replaceable in practice, for example if it has unconfirmed ancestors which\n"
|
||||
" are replaceable)."},
|
||||
{"estimate_mode", RPCArg::Type::STR, /* default */ "unset", std::string() + "The fee estimate mode, must be one of (case insensitive):\n"
|
||||
" \"" + FeeModes("\"\n\"") + "\""},
|
||||
},
|
||||
"options"},
|
||||
{"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks)"},
|
||||
{"fee_rate", RPCArg::Type::NUM, /* default */ "fall back to 'conf_target'", "fee rate (NOT total fee) to pay, in " + CURRENCY_UNIT + " per kB\n"
|
||||
" Specify a fee rate instead of relying on the built-in fee estimator.\n"
|
||||
"Must be at least 0.0001 " + CURRENCY_UNIT + " per kB higher than the current transaction fee rate.\n"},
|
||||
{"replaceable", RPCArg::Type::BOOL, /* default */ "true", "Whether the new transaction should still be\n"
|
||||
" marked bip-125 replaceable. If true, the sequence numbers in the transaction will\n"
|
||||
" be left unchanged from the original. If false, any input sequence numbers in the\n"
|
||||
" original transaction that were less than 0xfffffffe will be increased to 0xfffffffe\n"
|
||||
" so the new transaction will not be explicitly bip-125 replaceable (though it may\n"
|
||||
" still be replaceable in practice, for example if it has unconfirmed ancestors which\n"
|
||||
" are replaceable)."},
|
||||
{"estimate_mode", RPCArg::Type::STR, /* default */ "unset", std::string() + "The fee estimate mode, must be one of (case insensitive):\n"
|
||||
" \"" + FeeModes("\"\n\"") + "\""},
|
||||
},
|
||||
RPCResult{
|
||||
RPCResult::Type::OBJ, "", "", {
|
||||
{RPCResult::Type::STR, "psbt", "The base64-encoded unsigned PSBT of the new transaction. Only returned when wallet private keys are disabled."},
|
||||
{RPCResult::Type::STR_HEX, "txid", "The id of the new transaction. Only returned when wallet private keys are enabled."},
|
||||
{RPCResult::Type::STR_AMOUNT, "origfee", "The fee of the replaced transaction."},
|
||||
{RPCResult::Type::STR_AMOUNT, "fee", "The fee of the new transaction."},
|
||||
{RPCResult::Type::ARR, "errors", "Errors encountered during processing (may be empty).",
|
||||
{
|
||||
{RPCResult::Type::STR, "", ""},
|
||||
}},
|
||||
}
|
||||
},
|
||||
RPCExamples{
|
||||
"\nBump the fee, get the new transaction\'s txid\n" +
|
||||
HelpExampleCli("bumpfee", "<txid>")
|
||||
},
|
||||
}.Check(request);
|
||||
"options"},
|
||||
},
|
||||
RPCResult{
|
||||
RPCResult::Type::OBJ, "", "", Cat(Cat<std::vector<RPCResult>>(
|
||||
{
|
||||
{RPCResult::Type::STR, "psbt", "The base64-encoded unsigned PSBT of the new transaction." + std::string(want_psbt ? "" : " Only returned when wallet private keys are disabled. (DEPRECATED)")},
|
||||
},
|
||||
want_psbt ? std::vector<RPCResult>{} : std::vector<RPCResult>{{RPCResult::Type::STR_HEX, "txid", "The id of the new transaction. Only returned when wallet private keys are enabled."}}
|
||||
),
|
||||
{
|
||||
{RPCResult::Type::STR_AMOUNT, "origfee", "The fee of the replaced transaction."},
|
||||
{RPCResult::Type::STR_AMOUNT, "fee", "The fee of the new transaction."},
|
||||
{RPCResult::Type::ARR, "errors", "Errors encountered during processing (may be empty).",
|
||||
{
|
||||
{RPCResult::Type::STR, "", ""},
|
||||
}},
|
||||
})
|
||||
},
|
||||
RPCExamples{
|
||||
"\nBump the fee, get the new transaction\'s" + std::string(want_psbt ? "psbt" : "txid") + "\n" +
|
||||
HelpExampleCli(request.strMethod, "<txid>")
|
||||
},
|
||||
}.Check(request);
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !want_psbt) {
|
||||
if (!pwallet->chain().rpcEnableDeprecated("bumpfee")) {
|
||||
throw JSONRPCError(RPC_METHOD_DEPRECATED, "Using bumpfee with wallets that have private keys disabled is deprecated. Use psbtbumpfee instead or restart bitcoind with -deprecatedrpc=bumpfee. This functionality will be removed in 0.22");
|
||||
}
|
||||
want_psbt = true;
|
||||
}
|
||||
|
||||
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ});
|
||||
uint256 hash(ParseHashV(request.params[0], "txid"));
|
||||
|
||||
@@ -3359,7 +3373,7 @@ static UniValue bumpfee(const JSONRPCRequest& request)
|
||||
|
||||
// If wallet private keys are enabled, return the new transaction id,
|
||||
// otherwise return the base64-encoded unsigned PSBT of the new transaction.
|
||||
if (!pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
|
||||
if (!want_psbt) {
|
||||
if (!feebumper::SignTransaction(*pwallet, mtx)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Can't sign transaction.");
|
||||
}
|
||||
@@ -3392,6 +3406,11 @@ static UniValue bumpfee(const JSONRPCRequest& request)
|
||||
return result;
|
||||
}
|
||||
|
||||
static UniValue psbtbumpfee(const JSONRPCRequest& request)
|
||||
{
|
||||
return bumpfee(request);
|
||||
}
|
||||
|
||||
UniValue rescanblockchain(const JSONRPCRequest& request)
|
||||
{
|
||||
RPCHelpMan{"rescanblockchain",
|
||||
@@ -4137,6 +4156,7 @@ static const CRPCCommand commands[] =
|
||||
{ "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","label","address_type"} },
|
||||
{ "wallet", "backupwallet", &backupwallet, {"destination"} },
|
||||
{ "wallet", "bumpfee", &bumpfee, {"txid", "options"} },
|
||||
{ "wallet", "psbtbumpfee", &psbtbumpfee, {"txid", "options"} },
|
||||
{ "wallet", "createwallet", &createwallet, {"wallet_name", "disable_private_keys", "blank", "passphrase", "avoid_reuse", "descriptors"} },
|
||||
{ "wallet", "dumpprivkey", &dumpprivkey, {"address"} },
|
||||
{ "wallet", "dumpwallet", &dumpwallet, {"filename"} },
|
||||
|
||||
Reference in New Issue
Block a user