mirror of
https://github.com/Retropex/bitcoin.git
synced 2025-05-12 19:20: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
|
||||
const QStringList historyFilter = QStringList()
|
||||
<< "importprivkey"
|
||||
<< "importmulti"
|
||||
<< "sethdseed"
|
||||
<< "signmessagewithprivkey"
|
||||
<< "signrawtransactionwithkey"
|
||||
<< "walletpassphrase"
|
||||
|
@ -85,8 +85,6 @@ void RPCNestedTests::rpcNestedTests()
|
||||
QVERIFY(result == "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
|
||||
QVERIFY(filtered == "getblock(getbestblockhash())[tx][0]");
|
||||
|
||||
RPCConsole::RPCParseCommandLine(nullptr, result, "importprivkey", false, &filtered);
|
||||
QVERIFY(filtered == "importprivkey(…)");
|
||||
RPCConsole::RPCParseCommandLine(nullptr, result, "signmessagewithprivkey abc", false, &filtered);
|
||||
QVERIFY(filtered == "signmessagewithprivkey(…)");
|
||||
RPCConsole::RPCParseCommandLine(nullptr, result, "signmessagewithprivkey abc,def", false, &filtered);
|
||||
@ -99,12 +97,6 @@ void RPCNestedTests::rpcNestedTests()
|
||||
QVERIFY(filtered == "walletpassphrasechange(…)");
|
||||
RPCConsole::RPCParseCommandLine(nullptr, result, "help(encryptwallet(abc, def))", false, &filtered);
|
||||
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");
|
||||
QVERIFY(result == "[]");
|
||||
|
@ -48,7 +48,6 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
||||
{ "sendtoaddress", 9, "fee_rate"},
|
||||
{ "sendtoaddress", 10, "verbose"},
|
||||
{ "settxfee", 0, "amount" },
|
||||
{ "sethdseed", 0, "newkeypool" },
|
||||
{ "getreceivedbyaddress", 1, "minconf" },
|
||||
{ "getreceivedbyaddress", 2, "include_immature_coinbase" },
|
||||
{ "getreceivedbylabel", 1, "minconf" },
|
||||
@ -96,8 +95,6 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
||||
{ "getdescriptoractivity", 1, "scanobjects" },
|
||||
{ "getdescriptoractivity", 2, "include_mempool" },
|
||||
{ "scantxoutset", 1, "scanobjects" },
|
||||
{ "addmultisigaddress", 0, "nrequired" },
|
||||
{ "addmultisigaddress", 1, "keys" },
|
||||
{ "createmultisig", 0, "nrequired" },
|
||||
{ "createmultisig", 1, "keys" },
|
||||
{ "listunspent", 0, "minconf" },
|
||||
@ -236,17 +233,10 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
||||
{ "simulaterawtransaction", 0, "rawtxs" },
|
||||
{ "simulaterawtransaction", 1, "options" },
|
||||
{ "simulaterawtransaction", 1, "include_watchonly"},
|
||||
{ "importprivkey", 2, "rescan" },
|
||||
{ "importaddress", 2, "rescan" },
|
||||
{ "importaddress", 3, "p2sh" },
|
||||
{ "importpubkey", 2, "rescan" },
|
||||
{ "importmempool", 1, "options" },
|
||||
{ "importmempool", 1, "apply_fee_delta_priority" },
|
||||
{ "importmempool", 1, "use_current_time" },
|
||||
{ "importmempool", 1, "apply_unbroadcast_set" },
|
||||
{ "importmulti", 0, "requests" },
|
||||
{ "importmulti", 1, "options" },
|
||||
{ "importmulti", 1, "rescan" },
|
||||
{ "importdescriptors", 0, "requests" },
|
||||
{ "listdescriptors", 0, "private" },
|
||||
{ "verifychain", 0, "checklevel" },
|
||||
|
@ -75,14 +75,12 @@ const std::vector<std::string> RPC_COMMANDS_NOT_SAFE_FOR_FUZZING{
|
||||
"addnode", // avoid DNS lookups
|
||||
"addpeeraddress", // avoid DNS lookups
|
||||
"dumptxoutset", // avoid writing to disk
|
||||
"dumpwallet", // avoid writing to disk
|
||||
"enumeratesigners",
|
||||
"echoipc", // avoid assertion failure (Assertion `"EnsureAnyNodeContext(request.context).init" && check' failed.)
|
||||
"generatetoaddress", // avoid prohibitively slow execution (when `num_blocks` is large)
|
||||
"generatetodescriptor", // avoid prohibitively slow execution (when `nblocks` is large)
|
||||
"gettxoutproof", // avoid prohibitively slow execution
|
||||
"importmempool", // avoid reading from disk
|
||||
"importwallet", // avoid reading from disk
|
||||
"loadtxoutset", // avoid reading from disk
|
||||
"loadwallet", // avoid reading from disk
|
||||
"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()
|
||||
{
|
||||
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
|
||||
{
|
||||
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"
|
||||
"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"
|
||||
"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"
|
||||
"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\"."},
|
||||
{"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"
|
||||
"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"},
|
||||
{"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."},
|
||||
@ -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}},
|
||||
{"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"
|
||||
"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.",
|
||||
{
|
||||
{"", 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}},
|
||||
{"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"
|
||||
"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.",
|
||||
{
|
||||
{"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
|
||||
|
@ -946,13 +946,13 @@ RPCHelpMan rescanblockchain()
|
||||
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",
|
||||
{},
|
||||
RPCResult{RPCResult::Type::BOOL, "", "Whether the abort was successful"},
|
||||
RPCExamples{
|
||||
"\nImport a private key\n"
|
||||
+ HelpExampleCli("importprivkey", "\"mykey\"") +
|
||||
+ HelpExampleCli("rescanblockchain", "") +
|
||||
"\nAbort the running wallet rescan\n"
|
||||
+ HelpExampleCli("abortrescan", "") +
|
||||
"\nAs a JSON-RPC call\n"
|
||||
|
@ -94,28 +94,6 @@ WalletContext& EnsureWalletContext(const std::any& 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)
|
||||
{
|
||||
static const std::string empty_string;
|
||||
|
@ -41,8 +41,6 @@ bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest& request, std::string&
|
||||
|
||||
void EnsureWalletIsUnlocked(const CWallet&);
|
||||
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 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."},
|
||||
{"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."},
|
||||
{"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\""},
|
||||
@ -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()
|
||||
{
|
||||
return RPCHelpMan{"upgradewallet",
|
||||
@ -1024,9 +953,7 @@ RPCHelpMan getnewaddress();
|
||||
RPCHelpMan getrawchangeaddress();
|
||||
RPCHelpMan setlabel();
|
||||
RPCHelpMan listaddressgroupings();
|
||||
RPCHelpMan addmultisigaddress();
|
||||
RPCHelpMan keypoolrefill();
|
||||
RPCHelpMan newkeypool();
|
||||
RPCHelpMan getaddressesbylabel();
|
||||
RPCHelpMan listlabels();
|
||||
#ifdef ENABLE_EXTERNAL_SIGNER
|
||||
@ -1034,15 +961,8 @@ RPCHelpMan walletdisplayaddress();
|
||||
#endif // ENABLE_EXTERNAL_SIGNER
|
||||
|
||||
// backup
|
||||
RPCHelpMan dumpprivkey();
|
||||
RPCHelpMan importprivkey();
|
||||
RPCHelpMan importaddress();
|
||||
RPCHelpMan importpubkey();
|
||||
RPCHelpMan dumpwallet();
|
||||
RPCHelpMan importwallet();
|
||||
RPCHelpMan importprunedfunds();
|
||||
RPCHelpMan removeprunedfunds();
|
||||
RPCHelpMan importmulti();
|
||||
RPCHelpMan importdescriptors();
|
||||
RPCHelpMan listdescriptors();
|
||||
RPCHelpMan backupwallet();
|
||||
@ -1096,15 +1016,12 @@ std::span<const CRPCCommand> GetWalletRPCCommands()
|
||||
{"rawtransactions", &fundrawtransaction},
|
||||
{"wallet", &abandontransaction},
|
||||
{"wallet", &abortrescan},
|
||||
{"wallet", &addmultisigaddress},
|
||||
{"wallet", &backupwallet},
|
||||
{"wallet", &bumpfee},
|
||||
{"wallet", &psbtbumpfee},
|
||||
{"wallet", &createwallet},
|
||||
{"wallet", &createwalletdescriptor},
|
||||
{"wallet", &restorewallet},
|
||||
{"wallet", &dumpprivkey},
|
||||
{"wallet", &dumpwallet},
|
||||
{"wallet", &encryptwallet},
|
||||
{"wallet", &getaddressesbylabel},
|
||||
{"wallet", &getaddressinfo},
|
||||
@ -1118,13 +1035,8 @@ std::span<const CRPCCommand> GetWalletRPCCommands()
|
||||
{"wallet", &getunconfirmedbalance},
|
||||
{"wallet", &getbalances},
|
||||
{"wallet", &getwalletinfo},
|
||||
{"wallet", &importaddress},
|
||||
{"wallet", &importdescriptors},
|
||||
{"wallet", &importmulti},
|
||||
{"wallet", &importprivkey},
|
||||
{"wallet", &importprunedfunds},
|
||||
{"wallet", &importpubkey},
|
||||
{"wallet", &importwallet},
|
||||
{"wallet", &keypoolrefill},
|
||||
{"wallet", &listaddressgroupings},
|
||||
{"wallet", &listdescriptors},
|
||||
@ -1140,13 +1052,11 @@ std::span<const CRPCCommand> GetWalletRPCCommands()
|
||||
{"wallet", &loadwallet},
|
||||
{"wallet", &lockunspent},
|
||||
{"wallet", &migratewallet},
|
||||
{"wallet", &newkeypool},
|
||||
{"wallet", &removeprunedfunds},
|
||||
{"wallet", &rescanblockchain},
|
||||
{"wallet", &send},
|
||||
{"wallet", &sendmany},
|
||||
{"wallet", &sendtoaddress},
|
||||
{"wallet", &sethdseed},
|
||||
{"wallet", &setlabel},
|
||||
{"wallet", &settxfee},
|
||||
{"wallet", &setwalletflag},
|
||||
|
@ -35,9 +35,6 @@
|
||||
using node::MAX_BLOCKFILE_SIZE;
|
||||
|
||||
namespace wallet {
|
||||
RPCHelpMan importmulti();
|
||||
RPCHelpMan dumpwallet();
|
||||
RPCHelpMan importwallet();
|
||||
|
||||
// Ensure that fee levels defined in the wallet are at least as high
|
||||
// as the default levels for node policy.
|
||||
|
Loading…
Reference in New Issue
Block a user