mirror of
https://github.com/Retropex/bitcoin.git
synced 2025-05-13 03:30:42 +02:00
wallet, rpc: Remove legacy wallet only RPCs
This commit is contained in:
parent
4de3cec28d
commit
8ede6dea0c
@ -72,9 +72,6 @@ namespace {
|
|||||||
|
|
||||||
// don't add private key handling cmd's to the history
|
// don't add private key handling cmd's to the history
|
||||||
const QStringList historyFilter = QStringList()
|
const QStringList historyFilter = QStringList()
|
||||||
<< "importprivkey"
|
|
||||||
<< "importmulti"
|
|
||||||
<< "sethdseed"
|
|
||||||
<< "signmessagewithprivkey"
|
<< "signmessagewithprivkey"
|
||||||
<< "signrawtransactionwithkey"
|
<< "signrawtransactionwithkey"
|
||||||
<< "walletpassphrase"
|
<< "walletpassphrase"
|
||||||
|
@ -85,8 +85,6 @@ void RPCNestedTests::rpcNestedTests()
|
|||||||
QVERIFY(result == "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
|
QVERIFY(result == "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
|
||||||
QVERIFY(filtered == "getblock(getbestblockhash())[tx][0]");
|
QVERIFY(filtered == "getblock(getbestblockhash())[tx][0]");
|
||||||
|
|
||||||
RPCConsole::RPCParseCommandLine(nullptr, result, "importprivkey", false, &filtered);
|
|
||||||
QVERIFY(filtered == "importprivkey(…)");
|
|
||||||
RPCConsole::RPCParseCommandLine(nullptr, result, "signmessagewithprivkey abc", false, &filtered);
|
RPCConsole::RPCParseCommandLine(nullptr, result, "signmessagewithprivkey abc", false, &filtered);
|
||||||
QVERIFY(filtered == "signmessagewithprivkey(…)");
|
QVERIFY(filtered == "signmessagewithprivkey(…)");
|
||||||
RPCConsole::RPCParseCommandLine(nullptr, result, "signmessagewithprivkey abc,def", false, &filtered);
|
RPCConsole::RPCParseCommandLine(nullptr, result, "signmessagewithprivkey abc,def", false, &filtered);
|
||||||
@ -99,12 +97,6 @@ void RPCNestedTests::rpcNestedTests()
|
|||||||
QVERIFY(filtered == "walletpassphrasechange(…)");
|
QVERIFY(filtered == "walletpassphrasechange(…)");
|
||||||
RPCConsole::RPCParseCommandLine(nullptr, result, "help(encryptwallet(abc, def))", false, &filtered);
|
RPCConsole::RPCParseCommandLine(nullptr, result, "help(encryptwallet(abc, def))", false, &filtered);
|
||||||
QVERIFY(filtered == "help(encryptwallet(…))");
|
QVERIFY(filtered == "help(encryptwallet(…))");
|
||||||
RPCConsole::RPCParseCommandLine(nullptr, result, "help(importprivkey())", false, &filtered);
|
|
||||||
QVERIFY(filtered == "help(importprivkey(…))");
|
|
||||||
RPCConsole::RPCParseCommandLine(nullptr, result, "help(importprivkey(help()))", false, &filtered);
|
|
||||||
QVERIFY(filtered == "help(importprivkey(…))");
|
|
||||||
RPCConsole::RPCParseCommandLine(nullptr, result, "help(importprivkey(abc), walletpassphrase(def))", false, &filtered);
|
|
||||||
QVERIFY(filtered == "help(importprivkey(…), walletpassphrase(…))");
|
|
||||||
|
|
||||||
RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest");
|
RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest");
|
||||||
QVERIFY(result == "[]");
|
QVERIFY(result == "[]");
|
||||||
|
@ -48,7 +48,6 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
|||||||
{ "sendtoaddress", 9, "fee_rate"},
|
{ "sendtoaddress", 9, "fee_rate"},
|
||||||
{ "sendtoaddress", 10, "verbose"},
|
{ "sendtoaddress", 10, "verbose"},
|
||||||
{ "settxfee", 0, "amount" },
|
{ "settxfee", 0, "amount" },
|
||||||
{ "sethdseed", 0, "newkeypool" },
|
|
||||||
{ "getreceivedbyaddress", 1, "minconf" },
|
{ "getreceivedbyaddress", 1, "minconf" },
|
||||||
{ "getreceivedbyaddress", 2, "include_immature_coinbase" },
|
{ "getreceivedbyaddress", 2, "include_immature_coinbase" },
|
||||||
{ "getreceivedbylabel", 1, "minconf" },
|
{ "getreceivedbylabel", 1, "minconf" },
|
||||||
@ -96,8 +95,6 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
|||||||
{ "getdescriptoractivity", 1, "scanobjects" },
|
{ "getdescriptoractivity", 1, "scanobjects" },
|
||||||
{ "getdescriptoractivity", 2, "include_mempool" },
|
{ "getdescriptoractivity", 2, "include_mempool" },
|
||||||
{ "scantxoutset", 1, "scanobjects" },
|
{ "scantxoutset", 1, "scanobjects" },
|
||||||
{ "addmultisigaddress", 0, "nrequired" },
|
|
||||||
{ "addmultisigaddress", 1, "keys" },
|
|
||||||
{ "createmultisig", 0, "nrequired" },
|
{ "createmultisig", 0, "nrequired" },
|
||||||
{ "createmultisig", 1, "keys" },
|
{ "createmultisig", 1, "keys" },
|
||||||
{ "listunspent", 0, "minconf" },
|
{ "listunspent", 0, "minconf" },
|
||||||
@ -236,17 +233,10 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
|||||||
{ "simulaterawtransaction", 0, "rawtxs" },
|
{ "simulaterawtransaction", 0, "rawtxs" },
|
||||||
{ "simulaterawtransaction", 1, "options" },
|
{ "simulaterawtransaction", 1, "options" },
|
||||||
{ "simulaterawtransaction", 1, "include_watchonly"},
|
{ "simulaterawtransaction", 1, "include_watchonly"},
|
||||||
{ "importprivkey", 2, "rescan" },
|
|
||||||
{ "importaddress", 2, "rescan" },
|
|
||||||
{ "importaddress", 3, "p2sh" },
|
|
||||||
{ "importpubkey", 2, "rescan" },
|
|
||||||
{ "importmempool", 1, "options" },
|
{ "importmempool", 1, "options" },
|
||||||
{ "importmempool", 1, "apply_fee_delta_priority" },
|
{ "importmempool", 1, "apply_fee_delta_priority" },
|
||||||
{ "importmempool", 1, "use_current_time" },
|
{ "importmempool", 1, "use_current_time" },
|
||||||
{ "importmempool", 1, "apply_unbroadcast_set" },
|
{ "importmempool", 1, "apply_unbroadcast_set" },
|
||||||
{ "importmulti", 0, "requests" },
|
|
||||||
{ "importmulti", 1, "options" },
|
|
||||||
{ "importmulti", 1, "rescan" },
|
|
||||||
{ "importdescriptors", 0, "requests" },
|
{ "importdescriptors", 0, "requests" },
|
||||||
{ "listdescriptors", 0, "private" },
|
{ "listdescriptors", 0, "private" },
|
||||||
{ "verifychain", 0, "checklevel" },
|
{ "verifychain", 0, "checklevel" },
|
||||||
|
@ -75,14 +75,12 @@ const std::vector<std::string> RPC_COMMANDS_NOT_SAFE_FOR_FUZZING{
|
|||||||
"addnode", // avoid DNS lookups
|
"addnode", // avoid DNS lookups
|
||||||
"addpeeraddress", // avoid DNS lookups
|
"addpeeraddress", // avoid DNS lookups
|
||||||
"dumptxoutset", // avoid writing to disk
|
"dumptxoutset", // avoid writing to disk
|
||||||
"dumpwallet", // avoid writing to disk
|
|
||||||
"enumeratesigners",
|
"enumeratesigners",
|
||||||
"echoipc", // avoid assertion failure (Assertion `"EnsureAnyNodeContext(request.context).init" && check' failed.)
|
"echoipc", // avoid assertion failure (Assertion `"EnsureAnyNodeContext(request.context).init" && check' failed.)
|
||||||
"generatetoaddress", // avoid prohibitively slow execution (when `num_blocks` is large)
|
"generatetoaddress", // avoid prohibitively slow execution (when `num_blocks` is large)
|
||||||
"generatetodescriptor", // avoid prohibitively slow execution (when `nblocks` is large)
|
"generatetodescriptor", // avoid prohibitively slow execution (when `nblocks` is large)
|
||||||
"gettxoutproof", // avoid prohibitively slow execution
|
"gettxoutproof", // avoid prohibitively slow execution
|
||||||
"importmempool", // avoid reading from disk
|
"importmempool", // avoid reading from disk
|
||||||
"importwallet", // avoid reading from disk
|
|
||||||
"loadtxoutset", // avoid reading from disk
|
"loadtxoutset", // avoid reading from disk
|
||||||
"loadwallet", // avoid reading from disk
|
"loadwallet", // avoid reading from disk
|
||||||
"savemempool", // disabled as a precautionary measure: may take a file path argument in the future
|
"savemempool", // disabled as a precautionary measure: may take a file path argument in the future
|
||||||
|
@ -215,124 +215,6 @@ RPCHelpMan listaddressgroupings()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
RPCHelpMan addmultisigaddress()
|
|
||||||
{
|
|
||||||
return RPCHelpMan{"addmultisigaddress",
|
|
||||||
"\nAdd an nrequired-to-sign multisignature address to the wallet. Requires a new wallet backup.\n"
|
|
||||||
"Each key is a Bitcoin address or hex-encoded public key.\n"
|
|
||||||
"This functionality is only intended for use with non-watchonly addresses.\n"
|
|
||||||
"See `importaddress` for watchonly p2sh address support.\n"
|
|
||||||
"If 'label' is specified, assign address to that label.\n"
|
|
||||||
"Note: This command is only compatible with legacy wallets.\n",
|
|
||||||
{
|
|
||||||
{"nrequired", RPCArg::Type::NUM, RPCArg::Optional::NO, "The number of required signatures out of the n keys or addresses."},
|
|
||||||
{"keys", RPCArg::Type::ARR, RPCArg::Optional::NO, "The bitcoin addresses or hex-encoded public keys",
|
|
||||||
{
|
|
||||||
{"key", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "bitcoin address or hex-encoded public key"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{"label", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A label to assign the addresses to."},
|
|
||||||
{"address_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -addresstype"}, "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
|
|
||||||
},
|
|
||||||
RPCResult{
|
|
||||||
RPCResult::Type::OBJ, "", "",
|
|
||||||
{
|
|
||||||
{RPCResult::Type::STR, "address", "The value of the new multisig address"},
|
|
||||||
{RPCResult::Type::STR_HEX, "redeemScript", "The string value of the hex-encoded redemption script"},
|
|
||||||
{RPCResult::Type::STR, "descriptor", "The descriptor for this multisig"},
|
|
||||||
{RPCResult::Type::ARR, "warnings", /*optional=*/true, "Any warnings resulting from the creation of this multisig",
|
|
||||||
{
|
|
||||||
{RPCResult::Type::STR, "", ""},
|
|
||||||
}},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
RPCExamples{
|
|
||||||
"\nAdd a multisig address from 2 addresses\n"
|
|
||||||
+ HelpExampleCli("addmultisigaddress", "2 \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"") +
|
|
||||||
"\nAs a JSON-RPC call\n"
|
|
||||||
+ HelpExampleRpc("addmultisigaddress", "2, \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"")
|
|
||||||
},
|
|
||||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
|
||||||
{
|
|
||||||
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
|
|
||||||
if (!pwallet) return UniValue::VNULL;
|
|
||||||
|
|
||||||
LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*pwallet);
|
|
||||||
|
|
||||||
LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore);
|
|
||||||
|
|
||||||
const std::string label{LabelFromValue(request.params[2])};
|
|
||||||
|
|
||||||
int required = request.params[0].getInt<int>();
|
|
||||||
|
|
||||||
// Get the public keys
|
|
||||||
const UniValue& keys_or_addrs = request.params[1].get_array();
|
|
||||||
std::vector<CPubKey> pubkeys;
|
|
||||||
for (unsigned int i = 0; i < keys_or_addrs.size(); ++i) {
|
|
||||||
if (IsHex(keys_or_addrs[i].get_str()) && (keys_or_addrs[i].get_str().length() == 66 || keys_or_addrs[i].get_str().length() == 130)) {
|
|
||||||
pubkeys.push_back(HexToPubKey(keys_or_addrs[i].get_str()));
|
|
||||||
} else {
|
|
||||||
pubkeys.push_back(AddrToPubKey(spk_man, keys_or_addrs[i].get_str()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
OutputType output_type = pwallet->m_default_address_type;
|
|
||||||
if (!request.params[3].isNull()) {
|
|
||||||
std::optional<OutputType> parsed = ParseOutputType(request.params[3].get_str());
|
|
||||||
if (!parsed) {
|
|
||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[3].get_str()));
|
|
||||||
} else if (parsed.value() == OutputType::BECH32M) {
|
|
||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Bech32m multisig addresses cannot be created with legacy wallets");
|
|
||||||
}
|
|
||||||
output_type = parsed.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Construct multisig scripts
|
|
||||||
FlatSigningProvider provider;
|
|
||||||
CScript inner;
|
|
||||||
CTxDestination dest = AddAndGetMultisigDestination(required, pubkeys, output_type, provider, inner);
|
|
||||||
|
|
||||||
// Import scripts into the wallet
|
|
||||||
for (const auto& [id, script] : provider.scripts) {
|
|
||||||
// Due to a bug in the legacy wallet, the p2sh maximum script size limit is also imposed on 'p2sh-segwit' and 'bech32' redeem scripts.
|
|
||||||
// Even when redeem scripts over MAX_SCRIPT_ELEMENT_SIZE bytes are valid for segwit output types, we don't want to
|
|
||||||
// enable it because:
|
|
||||||
// 1) It introduces a compatibility-breaking change requiring downgrade protection; older wallets would be unable to interact with these "new" legacy wallets.
|
|
||||||
// 2) Considering the ongoing deprecation of the legacy spkm, this issue adds another good reason to transition towards descriptors.
|
|
||||||
if (script.size() > MAX_SCRIPT_ELEMENT_SIZE) throw JSONRPCError(RPC_WALLET_ERROR, "Unsupported multisig script size for legacy wallet. Upgrade to descriptors to overcome this limitation for p2sh-segwit or bech32 scripts");
|
|
||||||
|
|
||||||
if (!spk_man.AddCScript(script)) {
|
|
||||||
if (CScript inner_script; spk_man.GetCScript(CScriptID(script), inner_script)) {
|
|
||||||
CHECK_NONFATAL(inner_script == script); // Nothing to add, script already contained by the wallet
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Error importing script into the wallet"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store destination in the addressbook
|
|
||||||
pwallet->SetAddressBook(dest, label, AddressPurpose::SEND);
|
|
||||||
|
|
||||||
// Make the descriptor
|
|
||||||
std::unique_ptr<Descriptor> descriptor = InferDescriptor(GetScriptForDestination(dest), spk_man);
|
|
||||||
|
|
||||||
UniValue result(UniValue::VOBJ);
|
|
||||||
result.pushKV("address", EncodeDestination(dest));
|
|
||||||
result.pushKV("redeemScript", HexStr(inner));
|
|
||||||
result.pushKV("descriptor", descriptor->ToString());
|
|
||||||
|
|
||||||
UniValue warnings(UniValue::VARR);
|
|
||||||
if (descriptor->GetOutputType() != output_type) {
|
|
||||||
// Only warns if the user has explicitly chosen an address type we cannot generate
|
|
||||||
warnings.push_back("Unable to make chosen address type, please ensure no uncompressed public keys are present.");
|
|
||||||
}
|
|
||||||
PushWarnings(warnings, result);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
RPCHelpMan keypoolrefill()
|
RPCHelpMan keypoolrefill()
|
||||||
{
|
{
|
||||||
return RPCHelpMan{"keypoolrefill",
|
return RPCHelpMan{"keypoolrefill",
|
||||||
@ -377,38 +259,6 @@ RPCHelpMan keypoolrefill()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
RPCHelpMan newkeypool()
|
|
||||||
{
|
|
||||||
return RPCHelpMan{"newkeypool",
|
|
||||||
"\nEntirely clears and refills the keypool.\n"
|
|
||||||
"WARNING: On non-HD wallets, this will require a new backup immediately, to include the new keys.\n"
|
|
||||||
"When restoring a backup of an HD wallet created before the newkeypool command is run, funds received to\n"
|
|
||||||
"new addresses may not appear automatically. They have not been lost, but the wallet may not find them.\n"
|
|
||||||
"This can be fixed by running the newkeypool command on the backup and then rescanning, so the wallet\n"
|
|
||||||
"re-generates the required keys." +
|
|
||||||
HELP_REQUIRING_PASSPHRASE,
|
|
||||||
{},
|
|
||||||
RPCResult{RPCResult::Type::NONE, "", ""},
|
|
||||||
RPCExamples{
|
|
||||||
HelpExampleCli("newkeypool", "")
|
|
||||||
+ HelpExampleRpc("newkeypool", "")
|
|
||||||
},
|
|
||||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
|
||||||
{
|
|
||||||
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
|
|
||||||
if (!pwallet) return UniValue::VNULL;
|
|
||||||
|
|
||||||
LOCK(pwallet->cs_wallet);
|
|
||||||
|
|
||||||
LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*pwallet, true);
|
|
||||||
spk_man.NewKeyPool();
|
|
||||||
|
|
||||||
return UniValue::VNULL;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class DescribeWalletAddressVisitor
|
class DescribeWalletAddressVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -752,7 +752,7 @@ RPCHelpMan fundrawtransaction()
|
|||||||
"All existing inputs must either have their previous output transaction be in the wallet\n"
|
"All existing inputs must either have their previous output transaction be in the wallet\n"
|
||||||
"or be in the UTXO set. Solving data must be provided for non-wallet inputs.\n"
|
"or be in the UTXO set. Solving data must be provided for non-wallet inputs.\n"
|
||||||
"Note that all inputs selected must be of standard form and P2SH scripts must be\n"
|
"Note that all inputs selected must be of standard form and P2SH scripts must be\n"
|
||||||
"in the wallet using importaddress or addmultisigaddress (to calculate fees).\n"
|
"in the wallet using importdescriptors (to calculate fees).\n"
|
||||||
"You can see whether this is the case by checking the \"solvable\" field in the listunspent output.\n"
|
"You can see whether this is the case by checking the \"solvable\" field in the listunspent output.\n"
|
||||||
"Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n",
|
"Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n",
|
||||||
{
|
{
|
||||||
@ -771,7 +771,7 @@ RPCHelpMan fundrawtransaction()
|
|||||||
{"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
|
{"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
|
||||||
{"includeWatching", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also select inputs which are watch only.\n"
|
{"includeWatching", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also select inputs which are watch only.\n"
|
||||||
"Only solvable inputs can be used. Watch-only destinations are solvable if the public key and/or output script was imported,\n"
|
"Only solvable inputs can be used. Watch-only destinations are solvable if the public key and/or output script was imported,\n"
|
||||||
"e.g. with 'importpubkey' or 'importmulti' with the 'pubkeys' or 'desc' field."},
|
"e.g. with 'importdescriptors'."},
|
||||||
{"lockUnspents", RPCArg::Type::BOOL, RPCArg::Default{false}, "Lock selected unspent outputs"},
|
{"lockUnspents", RPCArg::Type::BOOL, RPCArg::Default{false}, "Lock selected unspent outputs"},
|
||||||
{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
|
{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
|
||||||
{"feeRate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_UNIT + "/kvB."},
|
{"feeRate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_UNIT + "/kvB."},
|
||||||
@ -1231,7 +1231,7 @@ RPCHelpMan send()
|
|||||||
{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB.", RPCArgOptions{.also_positional = true}},
|
{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB.", RPCArgOptions{.also_positional = true}},
|
||||||
{"include_watching", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also select inputs which are watch only.\n"
|
{"include_watching", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also select inputs which are watch only.\n"
|
||||||
"Only solvable inputs can be used. Watch-only destinations are solvable if the public key and/or output script was imported,\n"
|
"Only solvable inputs can be used. Watch-only destinations are solvable if the public key and/or output script was imported,\n"
|
||||||
"e.g. with 'importpubkey' or 'importmulti' with the 'pubkeys' or 'desc' field."},
|
"e.g. with 'importdescriptors'."},
|
||||||
{"inputs", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "Specify inputs instead of adding them automatically.",
|
{"inputs", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "Specify inputs instead of adding them automatically.",
|
||||||
{
|
{
|
||||||
{"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "", {
|
{"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "", {
|
||||||
@ -1351,7 +1351,7 @@ RPCHelpMan sendall()
|
|||||||
{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB.", RPCArgOptions{.also_positional = true}},
|
{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB.", RPCArgOptions{.also_positional = true}},
|
||||||
{"include_watching", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also select inputs which are watch-only.\n"
|
{"include_watching", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also select inputs which are watch-only.\n"
|
||||||
"Only solvable inputs can be used. Watch-only destinations are solvable if the public key and/or output script was imported,\n"
|
"Only solvable inputs can be used. Watch-only destinations are solvable if the public key and/or output script was imported,\n"
|
||||||
"e.g. with 'importpubkey' or 'importmulti' with the 'pubkeys' or 'desc' field."},
|
"e.g. with 'importdescriptors'."},
|
||||||
{"inputs", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "Use exactly the specified inputs to build the transaction. Specifying inputs is incompatible with the send_max, minconf, and maxconf options.",
|
{"inputs", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "Use exactly the specified inputs to build the transaction. Specifying inputs is incompatible with the send_max, minconf, and maxconf options.",
|
||||||
{
|
{
|
||||||
{"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
|
{"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
|
||||||
|
@ -946,13 +946,13 @@ RPCHelpMan rescanblockchain()
|
|||||||
RPCHelpMan abortrescan()
|
RPCHelpMan abortrescan()
|
||||||
{
|
{
|
||||||
return RPCHelpMan{"abortrescan",
|
return RPCHelpMan{"abortrescan",
|
||||||
"\nStops current wallet rescan triggered by an RPC call, e.g. by an importprivkey call.\n"
|
"\nStops current wallet rescan triggered by an RPC call, e.g. by an rescanblockchain call.\n"
|
||||||
"Note: Use \"getwalletinfo\" to query the scanning progress.\n",
|
"Note: Use \"getwalletinfo\" to query the scanning progress.\n",
|
||||||
{},
|
{},
|
||||||
RPCResult{RPCResult::Type::BOOL, "", "Whether the abort was successful"},
|
RPCResult{RPCResult::Type::BOOL, "", "Whether the abort was successful"},
|
||||||
RPCExamples{
|
RPCExamples{
|
||||||
"\nImport a private key\n"
|
"\nImport a private key\n"
|
||||||
+ HelpExampleCli("importprivkey", "\"mykey\"") +
|
+ HelpExampleCli("rescanblockchain", "") +
|
||||||
"\nAbort the running wallet rescan\n"
|
"\nAbort the running wallet rescan\n"
|
||||||
+ HelpExampleCli("abortrescan", "") +
|
+ HelpExampleCli("abortrescan", "") +
|
||||||
"\nAs a JSON-RPC call\n"
|
"\nAs a JSON-RPC call\n"
|
||||||
|
@ -94,28 +94,6 @@ WalletContext& EnsureWalletContext(const std::any& context)
|
|||||||
return *wallet_context;
|
return *wallet_context;
|
||||||
}
|
}
|
||||||
|
|
||||||
// also_create should only be set to true only when the RPC is expected to add things to a blank wallet and make it no longer blank
|
|
||||||
LegacyScriptPubKeyMan& EnsureLegacyScriptPubKeyMan(CWallet& wallet, bool also_create)
|
|
||||||
{
|
|
||||||
LegacyScriptPubKeyMan* spk_man = wallet.GetLegacyScriptPubKeyMan();
|
|
||||||
if (!spk_man && also_create) {
|
|
||||||
spk_man = wallet.GetOrCreateLegacyScriptPubKeyMan();
|
|
||||||
}
|
|
||||||
if (!spk_man) {
|
|
||||||
throw JSONRPCError(RPC_WALLET_ERROR, "Only legacy wallets are supported by this command");
|
|
||||||
}
|
|
||||||
return *spk_man;
|
|
||||||
}
|
|
||||||
|
|
||||||
const LegacyScriptPubKeyMan& EnsureConstLegacyScriptPubKeyMan(const CWallet& wallet)
|
|
||||||
{
|
|
||||||
const LegacyScriptPubKeyMan* spk_man = wallet.GetLegacyScriptPubKeyMan();
|
|
||||||
if (!spk_man) {
|
|
||||||
throw JSONRPCError(RPC_WALLET_ERROR, "Only legacy wallets are supported by this command");
|
|
||||||
}
|
|
||||||
return *spk_man;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string LabelFromValue(const UniValue& value)
|
std::string LabelFromValue(const UniValue& value)
|
||||||
{
|
{
|
||||||
static const std::string empty_string;
|
static const std::string empty_string;
|
||||||
|
@ -41,8 +41,6 @@ bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest& request, std::string&
|
|||||||
|
|
||||||
void EnsureWalletIsUnlocked(const CWallet&);
|
void EnsureWalletIsUnlocked(const CWallet&);
|
||||||
WalletContext& EnsureWalletContext(const std::any& context);
|
WalletContext& EnsureWalletContext(const std::any& context);
|
||||||
LegacyScriptPubKeyMan& EnsureLegacyScriptPubKeyMan(CWallet& wallet, bool also_create = false);
|
|
||||||
const LegacyScriptPubKeyMan& EnsureConstLegacyScriptPubKeyMan(const CWallet& wallet);
|
|
||||||
|
|
||||||
bool GetAvoidReuseFlag(const CWallet& wallet, const UniValue& param);
|
bool GetAvoidReuseFlag(const CWallet& wallet, const UniValue& param);
|
||||||
bool ParseIncludeWatchonly(const UniValue& include_watchonly, const CWallet& wallet);
|
bool ParseIncludeWatchonly(const UniValue& include_watchonly, const CWallet& wallet);
|
||||||
|
@ -352,7 +352,7 @@ static RPCHelpMan createwallet()
|
|||||||
{
|
{
|
||||||
{"wallet_name", RPCArg::Type::STR, RPCArg::Optional::NO, "The name for the new wallet. If this is a path, the wallet will be created at the path location."},
|
{"wallet_name", RPCArg::Type::STR, RPCArg::Optional::NO, "The name for the new wallet. If this is a path, the wallet will be created at the path location."},
|
||||||
{"disable_private_keys", RPCArg::Type::BOOL, RPCArg::Default{false}, "Disable the possibility of private keys (only watchonlys are possible in this mode)."},
|
{"disable_private_keys", RPCArg::Type::BOOL, RPCArg::Default{false}, "Disable the possibility of private keys (only watchonlys are possible in this mode)."},
|
||||||
{"blank", RPCArg::Type::BOOL, RPCArg::Default{false}, "Create a blank wallet. A blank wallet has no keys or HD seed. One can be set using sethdseed."},
|
{"blank", RPCArg::Type::BOOL, RPCArg::Default{false}, "Create a blank wallet. A blank wallet has no keys."},
|
||||||
{"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Encrypt the wallet with this passphrase."},
|
{"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Encrypt the wallet with this passphrase."},
|
||||||
{"avoid_reuse", RPCArg::Type::BOOL, RPCArg::Default{false}, "Keep track of coin reuse, and treat dirty and clean coins differently with privacy considerations in mind."},
|
{"avoid_reuse", RPCArg::Type::BOOL, RPCArg::Default{false}, "Keep track of coin reuse, and treat dirty and clean coins differently with privacy considerations in mind."},
|
||||||
{"descriptors", RPCArg::Type::BOOL, RPCArg::Default{true}, "If set, must be \"true\""},
|
{"descriptors", RPCArg::Type::BOOL, RPCArg::Default{true}, "If set, must be \"true\""},
|
||||||
@ -497,77 +497,6 @@ static RPCHelpMan unloadwallet()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static RPCHelpMan sethdseed()
|
|
||||||
{
|
|
||||||
return RPCHelpMan{"sethdseed",
|
|
||||||
"\nSet or generate a new HD wallet seed. Non-HD wallets will not be upgraded to being a HD wallet. Wallets that are already\n"
|
|
||||||
"HD will have a new HD seed set so that new keys added to the keypool will be derived from this new seed.\n"
|
|
||||||
"\nNote that you will need to MAKE A NEW BACKUP of your wallet after setting the HD wallet seed." + HELP_REQUIRING_PASSPHRASE +
|
|
||||||
"Note: This command is only compatible with legacy wallets.\n",
|
|
||||||
{
|
|
||||||
{"newkeypool", RPCArg::Type::BOOL, RPCArg::Default{true}, "Whether to flush old unused addresses, including change addresses, from the keypool and regenerate it.\n"
|
|
||||||
"If true, the next address from getnewaddress and change address from getrawchangeaddress will be from this new seed.\n"
|
|
||||||
"If false, addresses (including change addresses if the wallet already had HD Chain Split enabled) from the existing\n"
|
|
||||||
"keypool will be used until it has been depleted."},
|
|
||||||
{"seed", RPCArg::Type::STR, RPCArg::DefaultHint{"random seed"}, "The WIF private key to use as the new HD seed.\n"
|
|
||||||
"The seed value can be retrieved using the dumpwallet command. It is the private key marked hdseed=1"},
|
|
||||||
},
|
|
||||||
RPCResult{RPCResult::Type::NONE, "", ""},
|
|
||||||
RPCExamples{
|
|
||||||
HelpExampleCli("sethdseed", "")
|
|
||||||
+ HelpExampleCli("sethdseed", "false")
|
|
||||||
+ HelpExampleCli("sethdseed", "true \"wifkey\"")
|
|
||||||
+ HelpExampleRpc("sethdseed", "true, \"wifkey\"")
|
|
||||||
},
|
|
||||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
|
||||||
{
|
|
||||||
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
|
|
||||||
if (!pwallet) return UniValue::VNULL;
|
|
||||||
|
|
||||||
LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*pwallet, true);
|
|
||||||
|
|
||||||
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
|
|
||||||
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set a HD seed to a wallet with private keys disabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore);
|
|
||||||
|
|
||||||
// Do not do anything to non-HD wallets
|
|
||||||
if (!pwallet->CanSupportFeature(FEATURE_HD)) {
|
|
||||||
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set an HD seed on a non-HD wallet. Use the upgradewallet RPC in order to upgrade a non-HD wallet to HD");
|
|
||||||
}
|
|
||||||
|
|
||||||
EnsureWalletIsUnlocked(*pwallet);
|
|
||||||
|
|
||||||
bool flush_key_pool = true;
|
|
||||||
if (!request.params[0].isNull()) {
|
|
||||||
flush_key_pool = request.params[0].get_bool();
|
|
||||||
}
|
|
||||||
|
|
||||||
CPubKey master_pub_key;
|
|
||||||
if (request.params[1].isNull()) {
|
|
||||||
master_pub_key = spk_man.GenerateNewSeed();
|
|
||||||
} else {
|
|
||||||
CKey key = DecodeSecret(request.params[1].get_str());
|
|
||||||
if (!key.IsValid()) {
|
|
||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HaveKey(spk_man, key)) {
|
|
||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Already have this key (either as an HD seed or as a loose private key)");
|
|
||||||
}
|
|
||||||
|
|
||||||
master_pub_key = spk_man.DeriveNewSeed(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
spk_man.SetHDSeed(master_pub_key);
|
|
||||||
if (flush_key_pool) spk_man.NewKeyPool();
|
|
||||||
|
|
||||||
return UniValue::VNULL;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static RPCHelpMan upgradewallet()
|
static RPCHelpMan upgradewallet()
|
||||||
{
|
{
|
||||||
return RPCHelpMan{"upgradewallet",
|
return RPCHelpMan{"upgradewallet",
|
||||||
@ -1024,9 +953,7 @@ RPCHelpMan getnewaddress();
|
|||||||
RPCHelpMan getrawchangeaddress();
|
RPCHelpMan getrawchangeaddress();
|
||||||
RPCHelpMan setlabel();
|
RPCHelpMan setlabel();
|
||||||
RPCHelpMan listaddressgroupings();
|
RPCHelpMan listaddressgroupings();
|
||||||
RPCHelpMan addmultisigaddress();
|
|
||||||
RPCHelpMan keypoolrefill();
|
RPCHelpMan keypoolrefill();
|
||||||
RPCHelpMan newkeypool();
|
|
||||||
RPCHelpMan getaddressesbylabel();
|
RPCHelpMan getaddressesbylabel();
|
||||||
RPCHelpMan listlabels();
|
RPCHelpMan listlabels();
|
||||||
#ifdef ENABLE_EXTERNAL_SIGNER
|
#ifdef ENABLE_EXTERNAL_SIGNER
|
||||||
@ -1034,15 +961,8 @@ RPCHelpMan walletdisplayaddress();
|
|||||||
#endif // ENABLE_EXTERNAL_SIGNER
|
#endif // ENABLE_EXTERNAL_SIGNER
|
||||||
|
|
||||||
// backup
|
// backup
|
||||||
RPCHelpMan dumpprivkey();
|
|
||||||
RPCHelpMan importprivkey();
|
|
||||||
RPCHelpMan importaddress();
|
|
||||||
RPCHelpMan importpubkey();
|
|
||||||
RPCHelpMan dumpwallet();
|
|
||||||
RPCHelpMan importwallet();
|
|
||||||
RPCHelpMan importprunedfunds();
|
RPCHelpMan importprunedfunds();
|
||||||
RPCHelpMan removeprunedfunds();
|
RPCHelpMan removeprunedfunds();
|
||||||
RPCHelpMan importmulti();
|
|
||||||
RPCHelpMan importdescriptors();
|
RPCHelpMan importdescriptors();
|
||||||
RPCHelpMan listdescriptors();
|
RPCHelpMan listdescriptors();
|
||||||
RPCHelpMan backupwallet();
|
RPCHelpMan backupwallet();
|
||||||
@ -1096,15 +1016,12 @@ std::span<const CRPCCommand> GetWalletRPCCommands()
|
|||||||
{"rawtransactions", &fundrawtransaction},
|
{"rawtransactions", &fundrawtransaction},
|
||||||
{"wallet", &abandontransaction},
|
{"wallet", &abandontransaction},
|
||||||
{"wallet", &abortrescan},
|
{"wallet", &abortrescan},
|
||||||
{"wallet", &addmultisigaddress},
|
|
||||||
{"wallet", &backupwallet},
|
{"wallet", &backupwallet},
|
||||||
{"wallet", &bumpfee},
|
{"wallet", &bumpfee},
|
||||||
{"wallet", &psbtbumpfee},
|
{"wallet", &psbtbumpfee},
|
||||||
{"wallet", &createwallet},
|
{"wallet", &createwallet},
|
||||||
{"wallet", &createwalletdescriptor},
|
{"wallet", &createwalletdescriptor},
|
||||||
{"wallet", &restorewallet},
|
{"wallet", &restorewallet},
|
||||||
{"wallet", &dumpprivkey},
|
|
||||||
{"wallet", &dumpwallet},
|
|
||||||
{"wallet", &encryptwallet},
|
{"wallet", &encryptwallet},
|
||||||
{"wallet", &getaddressesbylabel},
|
{"wallet", &getaddressesbylabel},
|
||||||
{"wallet", &getaddressinfo},
|
{"wallet", &getaddressinfo},
|
||||||
@ -1118,13 +1035,8 @@ std::span<const CRPCCommand> GetWalletRPCCommands()
|
|||||||
{"wallet", &getunconfirmedbalance},
|
{"wallet", &getunconfirmedbalance},
|
||||||
{"wallet", &getbalances},
|
{"wallet", &getbalances},
|
||||||
{"wallet", &getwalletinfo},
|
{"wallet", &getwalletinfo},
|
||||||
{"wallet", &importaddress},
|
|
||||||
{"wallet", &importdescriptors},
|
{"wallet", &importdescriptors},
|
||||||
{"wallet", &importmulti},
|
|
||||||
{"wallet", &importprivkey},
|
|
||||||
{"wallet", &importprunedfunds},
|
{"wallet", &importprunedfunds},
|
||||||
{"wallet", &importpubkey},
|
|
||||||
{"wallet", &importwallet},
|
|
||||||
{"wallet", &keypoolrefill},
|
{"wallet", &keypoolrefill},
|
||||||
{"wallet", &listaddressgroupings},
|
{"wallet", &listaddressgroupings},
|
||||||
{"wallet", &listdescriptors},
|
{"wallet", &listdescriptors},
|
||||||
@ -1140,13 +1052,11 @@ std::span<const CRPCCommand> GetWalletRPCCommands()
|
|||||||
{"wallet", &loadwallet},
|
{"wallet", &loadwallet},
|
||||||
{"wallet", &lockunspent},
|
{"wallet", &lockunspent},
|
||||||
{"wallet", &migratewallet},
|
{"wallet", &migratewallet},
|
||||||
{"wallet", &newkeypool},
|
|
||||||
{"wallet", &removeprunedfunds},
|
{"wallet", &removeprunedfunds},
|
||||||
{"wallet", &rescanblockchain},
|
{"wallet", &rescanblockchain},
|
||||||
{"wallet", &send},
|
{"wallet", &send},
|
||||||
{"wallet", &sendmany},
|
{"wallet", &sendmany},
|
||||||
{"wallet", &sendtoaddress},
|
{"wallet", &sendtoaddress},
|
||||||
{"wallet", &sethdseed},
|
|
||||||
{"wallet", &setlabel},
|
{"wallet", &setlabel},
|
||||||
{"wallet", &settxfee},
|
{"wallet", &settxfee},
|
||||||
{"wallet", &setwalletflag},
|
{"wallet", &setwalletflag},
|
||||||
|
@ -35,9 +35,6 @@
|
|||||||
using node::MAX_BLOCKFILE_SIZE;
|
using node::MAX_BLOCKFILE_SIZE;
|
||||||
|
|
||||||
namespace wallet {
|
namespace wallet {
|
||||||
RPCHelpMan importmulti();
|
|
||||||
RPCHelpMan dumpwallet();
|
|
||||||
RPCHelpMan importwallet();
|
|
||||||
|
|
||||||
// Ensure that fee levels defined in the wallet are at least as high
|
// Ensure that fee levels defined in the wallet are at least as high
|
||||||
// as the default levels for node policy.
|
// as the default levels for node policy.
|
||||||
|
Loading…
Reference in New Issue
Block a user